//grafische Darstellung Einstieg Long private void PrepareTradeLong() { string strArrowUp = "ArrowUp" + Bars.GetTime(CurrentBar); DrawArrowUp(strArrowUp, true, Bars.GetTime(Count - 1), Bars.GetOpen(CurrentBar) - 100 * TickSize, Color.Green); GapTradeLong = true; }
//grafische Darstellung Einstieg Short private void PrepareTradeShort() { string strArrowDown = "ArrowDown" + Bars.GetTime(ProcessingBarIndex); AddChartArrowDown(strArrowDown, true, Bars.GetTime(Count - 1), Bars.GetOpen(ProcessingBarIndex) + 100 * TickSize, Color.Red); GapTradeShort = true; }
//grafische Darstellung Einstieg Short private void PrepareTradeShort() { string strArrowDown = "ArrowDown" + Bars.GetTime(CurrentBar); DrawArrowDown(strArrowDown, true, Bars.GetTime(Count - 1), Bars.GetOpen(CurrentBar) + 100 * TickSize, Color.Red); GapTradeShort = true; }
/// <summary> /// Hold the indicator volume from the underlining indicator /// /// </summary> #region Methods public double GetPriceByType(int barNo, PriceSubtype priceType) { Print(CurrentBar + ":GetPriceByType=" + barNo + "," + priceType); double prc = 0; switch (priceType) { case PriceSubtype.Low: prc = Bars.GetLow(barNo); break; case PriceSubtype.High: prc = Bars.GetHigh(barNo); break; case PriceSubtype.Open: prc = Bars.GetOpen(barNo); break; case PriceSubtype.Close: prc = Bars.GetClose(barNo); break; } return(prc); }
//grafische Darstellung Einstieg Long private void PrepareTradeLong() { string strArrowUp = "ArrowUp" + Bars.GetTime(ProcessingBarIndex); AddChartArrowUp(strArrowUp, true, Bars.GetTime(Count - 1), Bars.GetOpen(ProcessingBarIndex) - 100 * TickSize, Color.Green); GapTradeLong = true; }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { Bars bars = chartBars.Bars; float lineWidth = (float)Math.Max(1, BarWidth); Vector2 point0 = new Vector2(); Vector2 point1 = new Vector2(); Vector2 point2 = new Vector2(); Vector2 point3 = new Vector2(); Vector2 point4 = new Vector2(); Vector2 point5 = new Vector2(); for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++) { SharpDX.Direct2D1.Brush overriddenBrush = chartControl.GetBarOverrideBrush(chartBars, idx); double closeValue = bars.GetClose(idx); float close = chartScale.GetYByValue(closeValue); float high = chartScale.GetYByValue(bars.GetHigh(idx)); float low = chartScale.GetYByValue(bars.GetLow(idx)); double openValue = bars.GetOpen(idx); float open = chartScale.GetYByValue(openValue); float x = chartControl.GetXByBarIndex(chartBars, idx); point0.X = point1.X = x; point0.Y = high - lineWidth * 0.5f; point1.Y = low + lineWidth * 0.5f; SharpDX.Direct2D1.Brush b = overriddenBrush ?? (closeValue >= openValue ? UpBrushDX : DownBrushDX); if (!(b is SharpDX.Direct2D1.SolidColorBrush)) { TransformBrush(b, new RectangleF(point0.X - lineWidth * 1.5f, point0.Y, lineWidth * 3, point1.Y - point0.Y)); } RenderTarget.DrawLine(point0, point1, b, lineWidth); if (!Equals(Mode, OhlcMode.HiLo)) { point2.X = x + lineWidth * 1.5f; point2.Y = close; point3.X = x; point3.Y = close; RenderTarget.DrawLine(point2, point3, b, lineWidth); if (Equals(Mode, OhlcMode.OHLC)) { point4.X = x - lineWidth * 1.5f; point4.Y = open; point5.X = x; point5.Y = open; RenderTarget.DrawLine(point4, point5, b, lineWidth); } } } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { Bars bars = chartBars.Bars; float barWidth = GetBarPaintWidth(BarWidthUI); RectangleF rect = new RectangleF(); for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++) { Brush overriddenBrush = chartControl.GetBarOverrideBrush(chartBars, idx); Brush overriddenOutlineBrush = chartControl.GetCandleOutlineOverrideBrush(chartBars, idx); double closeValue = bars.GetClose(idx); float close = chartScale.GetYByValue(closeValue); double openValue = bars.GetOpen(idx); float open = chartScale.GetYByValue(openValue); float x = chartControl.GetXByBarIndex(chartBars, idx); Gui.Stroke outlineStroke = closeValue >= openValue ? Stroke : Stroke2; rect.X = x - barWidth * 0.5f + 0.5f; rect.Y = Math.Min(open, close); rect.Width = barWidth - 1; rect.Height = Math.Max(open, close) - Math.Min(open, close); Brush b = overriddenBrush ?? (closeValue >= openValue ? UpBrushDX : DownBrushDX); if (!(b is SolidColorBrush)) { TransformBrush(b, rect); } RenderTarget.FillRectangle(rect, b); b = overriddenBrush ?? outlineStroke.BrushDX; if (!(b is SolidColorBrush)) { TransformBrush(b, rect); } RenderTarget.DrawRectangle(rect, overriddenOutlineBrush ?? outlineStroke.BrushDX, outlineStroke.Width, outlineStroke.StrokeStyle); } }
protected override void OnCalculate() { string strReversalTradeLong = "ReversalTradeLong" + ProcessingBarIndex; string strReversalTradeShort = "ReversalTradeShort" + ProcessingBarIndex; string strTradeResultLong; string strTradeResultShort; Color colorTextBox; // 1 umkehr fallend auf steigend //-1 umkehr steigend auf fallend if (IsReversalLongTrade() == true) { ReversalTradeStartTSLong = Bars[0].Time; //TargetBarTime = GetTargetBar(Bars[0].Time); TargetBarTime = GlobalUtilities.GetTargetBar(Bars, Bars[0].Time, TimeFrame, 1); OutSeries.Set(100); Reversal2NextBar.Set(100); } else if (IsReversalShortTrade() == true) { ReversalTradeStartTSShort = Bars[0].Time; //TargetBarTime = GetTargetBar(Bars[0].Time); TargetBarTime = GlobalUtilities.GetTargetBar(Bars, Bars[0].Time, TimeFrame, 1); OutSeries.Set(-100); } else { Reversal2NextBar.Set(0); } //TradingKerze ist fertig, Zeiteinheit ist abgelaufen if (Bars[0].Time == TargetBarTime) { ReversalTradeResult = (decimal)Bars.GetClose(ProcessingBarIndex) - (decimal)Bars.GetOpen(ProcessingBarIndex); TradeCounter += 1; if (ReversalTradeStartTSLong > DateTime.MinValue) { ReversalTradeResultTotalLong = ReversalTradeResultTotalLong + ReversalTradeResult; if (ReversalTradeResult < 0) { strTradeResultLong = "Fail " + ReversalTradeResult.ToString(); colorTextBox = colFail; TradeCounterLongFail += 1; } else { strTradeResultLong = "Win " + ReversalTradeResult.ToString(); colorTextBox = colWin; TradeCounterLongWin += 1; } AddChartText(strReversalTradeLong, true, strTradeResultLong, Time[1], Bars.GetHigh(ProcessingBarIndex) + (100 * TickSize), 9, Color.Black, new Font("Arial", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } else if (ReversalTradeStartTSShort > DateTime.MinValue) { ReversalTradeResultTotalShort = ReversalTradeResultTotalShort + ReversalTradeResult; if (ReversalTradeResult < 0) { strTradeResultShort = "Win " + ReversalTradeResult.ToString(); colorTextBox = colWin; TradeCounterShortWin += 1; } else { strTradeResultShort = "Fail " + ReversalTradeResult.ToString(); colorTextBox = colFail; TradeCounterShortFail += 1; } AddChartText(strReversalTradeShort, true, strTradeResultShort, Time[1], Bars.GetHigh(ProcessingBarIndex) - (100 * TickSize), 9, Color.Black, new Font("Arial", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } //Variablen Resetten ReversalTradeStartTSLong = DateTime.MinValue; ReversalTradeStartTSShort = DateTime.MinValue; } if (IsProcessingBarIndexLast) { // Print("LongWin: " + TradeCounterLongWin + " LongFail: " + TradeCounterLongFail + " ShortWin: " + TradeCounterShortWin + " ShortFail: " + TradeCounterShortFail); // Print(Instrument.Name + "Trades: " + TradeCounter + " LongPunkte: " + ReversalTradeResultTotalLong + " ShortPunkte: " + ReversalTradeResultTotalShort); } }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } #region Building Bars from Base Period if (bars.Count != tmpCount) // Reset cache when bars are trimmed { if (bars.Count == 0) { tmpTime = Core.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; bars.LastPrice = bars.GetClose(bars.Count - 1); anchorPrice = bars.LastPrice; } } bool isNewSession = SessionIterator.IsNewSession(time, isBar); bool isCalculateTradingDayDone = false; switch (bars.BarsPeriod.BaseBarsPeriodType) { case BarsPeriodType.Day: tmpTime = time.Date; // Will be modified for realtime only if (!isBar && time >= cacheSessionEnd /* on realtime includesEndTimeStamp is always false */) { if (isNewSession) { SessionIterator.GetNextSession(time, isBar); isCalculateTradingDayDone = true; } cacheSessionEnd = SessionIterator.ActualSessionEnd; if (tmpTime < time.Date) { tmpTime = time.Date; // Make sure timestamps are ascending } } if (prevTime != tmpTime) { tmpDayCount++; } if (tmpDayCount < bars.BarsPeriod.BaseBarsPeriodValue || isBar && bars.Count > 0 && tmpTime == bars.LastBarTime.Date || !isBar && bars.Count > 0 && tmpTime <= bars.LastBarTime.Date) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; } break; case BarsPeriodType.Minute: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeMinute(bars, time, isBar); } if (isBar && time <= tmpTime || !isBar && time < tmpTime) { endOfBar = false; } else { prevTime = tmpTime; tmpTime = TimeToBarTimeMinute(bars, time, isBar); endOfBar = true; } break; case BarsPeriodType.Volume: if (tmpTime == Core.Globals.MinDate) { tmpVolume = volume; endOfBar = tmpVolume >= bars.BarsPeriod.BaseBarsPeriodValue; prevTime = tmpTime = time; if (endOfBar) { tmpVolume = 0; } break; } tmpVolume += volume; endOfBar = tmpVolume >= bars.BarsPeriod.BaseBarsPeriodValue; if (endOfBar) { prevTime = tmpTime; tmpVolume = 0; } tmpTime = time; break; case BarsPeriodType.Tick: if (tmpTime == Core.Globals.MinDate || bars.BarsPeriod.BaseBarsPeriodValue == 1) { prevTime = tmpTime == Core.Globals.MinDate ? time : tmpTime; tmpTime = time; tmpTickCount = bars.BarsPeriod.BaseBarsPeriodValue == 1 ? 0 : 1; endOfBar = bars.BarsPeriod.BaseBarsPeriodValue == 1; break; } if (tmpTickCount < bars.BarsPeriod.BaseBarsPeriodValue) { tmpTime = time; endOfBar = false; tmpTickCount++; } else { prevTime = tmpTime; tmpTime = time; endOfBar = true; tmpTickCount = 1; } break; case BarsPeriodType.Month: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeMonth(time, bars.BarsPeriod.BaseBarsPeriodValue); } if (time.Month <= tmpTime.Month && time.Year == tmpTime.Year || time.Year < tmpTime.Year) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeMonth(time, bars.BarsPeriod.BaseBarsPeriodValue); } break; case BarsPeriodType.Second: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeSecond(bars, time, isBar); } if (bars.BarsPeriod.BaseBarsPeriodValue > 1 && time < tmpTime || bars.BarsPeriod.BaseBarsPeriodValue == 1 && time <= tmpTime) { endOfBar = false; } else { prevTime = tmpTime; tmpTime = TimeToBarTimeSecond(bars, time, isBar); endOfBar = true; } break; case BarsPeriodType.Week: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.BarsPeriod.BaseBarsPeriodValue); } if (time.Date <= tmpTime.Date) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.BarsPeriod.BaseBarsPeriodValue); } break; case BarsPeriodType.Year: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeYear(time, bars.BarsPeriod.Value); } if (time.Year <= tmpTime.Year) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeYear(time, bars.BarsPeriod.Value); } break; } #endregion #region Kagi Logic reversalPoint = bars.BarsPeriod.ReversalType == ReversalType.Tick ? bars.BarsPeriod.Value * bars.Instrument.MasterInstrument.TickSize : bars.BarsPeriod.Value / 100.0 * anchorPrice; if (bars.Count == 0 || IsIntraday && (bars.BarsPeriod.BaseBarsPeriodType != BarsPeriodType.Second && bars.IsResetOnNewTradingDay && isNewSession || bars.BarsPeriod.BaseBarsPeriodType == BarsPeriodType.Second && bars.IsResetOnNewTradingDay && isNewSession)) { if (isNewSession && !isCalculateTradingDayDone) { SessionIterator.GetNextSession(tmpTime, isBar); } if (bars.Count > 0) { double lastOpen = bars.GetOpen(bars.Count - 1); double lastHigh = bars.GetHigh(bars.Count - 1); double lastLow = bars.GetLow(bars.Count - 1); double lastClose = bars.GetClose(bars.Count - 1); if (bars.Count == tmpCount) { CalculateKagiBar(bars, lastOpen, lastHigh, lastLow, lastClose, prevTime, volume); } } AddBar(bars, close, close, close, close, tmpTime, volume); anchorPrice = close; trend = Trend.Undetermined; prevTime = tmpTime; volumeCount = 0; bars.LastPrice = close; tmpCount = bars.Count; return; } double c = bars.GetClose(bars.Count - 1); double o = bars.GetOpen(bars.Count - 1); double h = bars.GetHigh(bars.Count - 1); double l = bars.GetLow(bars.Count - 1); if (endOfBar) { CalculateKagiBar(bars, o, h, l, c, prevTime, volume); } else { volumeCount += volume; } bars.LastPrice = close; tmpCount = bars.Count; #endregion }
/// <summary> /// </summary> /// <param name="bars"></param> /// <param name="open"></param> /// <param name="high"></param> /// <param name="low"></param> /// <param name="close"></param> /// <param name="time"></param> /// <param name="volume"></param> /// <param name="isRealtime"></param> public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { #region Building Bars from Base Period if (bars.Count != tmpCount) // reset cache when bars are trimmed if (bars.Count == 0) { tmpTime = Cbi.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; bars.LastPrice = bars.GetClose(bars.Count - 1); anchorPrice = bars.LastPrice; } switch (bars.Period.BasePeriodType) { case PeriodType.Day: tmpTime = time.Date; // will be modified for realtime only if (isRealtime && time >= cacheSessionEnd /* on realtime include60 is always false */) { bars.Session.GetSessionDate(time, false, out tmpTime, out cacheSessionEnd); if (tmpTime < time.Date) tmpTime = time.Date; // make sure timestamps are ascending } if (prevTime != tmpTime) tmpDayCount++; if (tmpDayCount < bars.Period.BasePeriodValue || (!isRealtime && bars.Count > 0 && tmpTime == bars.TimeLastBar.Date) || (isRealtime && bars.Count > 0 && tmpTime <= bars.TimeLastBar.Date)) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; } break; case PeriodType.Minute: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); if (!isRealtime && time <= tmpTime || isRealtime && time < tmpTime) endOfBar = false; else { prevTime = tmpTime; tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); endOfBar = true; } break; case PeriodType.Volume: if (tmpTime == Cbi.Globals.MinDate) { tmpVolume = volume; endOfBar = tmpVolume >= bars.Period.BasePeriodValue; prevTime = tmpTime = time; if (endOfBar) tmpVolume = 0; break; } tmpVolume += volume; endOfBar = tmpVolume >= bars.Period.BasePeriodValue; if (endOfBar) { prevTime = tmpTime; tmpVolume = 0; } tmpTime = time; break; case PeriodType.Tick: if (tmpTime == Cbi.Globals.MinDate || bars.Period.BasePeriodValue == 1) { prevTime = tmpTime == Cbi.Globals.MinDate ? time : tmpTime; tmpTime = time; tmpTickCount = bars.Period.BasePeriodValue == 1 ? 0 : 1; endOfBar = bars.Period.BasePeriodValue == 1; break; } if (tmpTickCount < bars.Period.BasePeriodValue) { tmpTime = time; endOfBar = false; tmpTickCount++; } else { prevTime = tmpTime; tmpTime = time; endOfBar = true; tmpTickCount = 1; } break; case PeriodType.Month: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); if (time.Month <= tmpTime.Month && time.Year == tmpTime.Year || time.Year < tmpTime.Year) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); } break; case PeriodType.Second: if (tmpTime == Cbi.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeSecond(bars, time, new DateTime( bars.Session.NextBeginTime.Year, bars.Session.NextBeginTime.Month, bars.Session.NextBeginTime.Day, bars.Session.NextBeginTime.Hour, bars.Session.NextBeginTime.Minute, 0), bars.Period.BasePeriodValue); } if ((bars.Period.Value > 1 && time < tmpTime) || (bars.Period.Value == 1 && time <= tmpTime)) endOfBar = false; else { prevTime = tmpTime; tmpTime = TimeToBarTimeSecond(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue); endOfBar = true; } break; case PeriodType.Week: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); if (time.Date <= tmpTime.Date) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); } break; case PeriodType.Year: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeYear(time, bars.Period.Value); if (time.Year <= tmpTime.Year) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeYear(time, bars.Period.Value); } break; } #endregion #region Kagi Logic reversalPoint = bars.Period.ReversalType == ReversalType.Tick ? bars.Period.Value * bars.Instrument.MasterInstrument.TickSize : bars.Period.Value * 0.01 * anchorPrice; if (bars.Count == 0 || (IsIntraday && ((bars.Period.BasePeriodType != PeriodType.Second && bars.IsNewSession(time, isRealtime)) || (bars.Period.BasePeriodType == PeriodType.Second && bars.IsNewSession(tmpTime, isRealtime))))) { if (bars.Count > 0) { double lastOpen = bars.GetOpen(bars.Count - 1); double lastHigh = bars.GetHigh(bars.Count - 1); double lastLow = bars.GetLow(bars.Count - 1); double lastClose = bars.GetClose(bars.Count - 1); if (bars.Count == tmpCount) CalculateKagiBar(bars, lastOpen, lastHigh, lastLow, lastClose, prevTime, volume, isRealtime); } AddBar(bars, close, close, close, close, tmpTime, volume, isRealtime); anchorPrice = close; trend = Trend.Undetermined; prevTime = tmpTime; volumeCount = 0; bars.LastPrice = close; tmpCount = bars.Count; return; } Bar bar = (Bar)bars.Get(bars.Count - 1); double c = bar.Close; double o = bar.Open; double h = bar.High; double l = bar.Low; if (endOfBar) CalculateKagiBar(bars, o, h, l, c, prevTime, volume, isRealtime); else volumeCount += volume; bars.LastPrice = close; tmpCount = bars.Count; #endregion }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { // method variables bool isNewSession = SessionIterator.IsNewSession(time, isBar); double tickSize = bars.Instrument.MasterInstrument.TickSize; if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } if (bars.Count == 0 || (bars.IsResetOnNewTradingDay && isNewSession)) { // update fields rangeMax = AddTwoDoubles(bars, bars.BarsPeriod.BaseBarsPeriodValue * tickSize, 0); rangeMin = AddTwoDoubles(bars, bars.BarsPeriod.Value * tickSize, 0); // set initial range, factoring dynamic thisRange = isDynamic ? rangeMin : rangeMax; AdjustMaxMin(bars, close, close); // add first bar AddBar(bars, thisOpen, thisOpen, thisOpen, thisOpen, time, volume); } else { // local variables double barOpen = bars.GetOpen(bars.Count - 1); double barHigh = bars.GetHigh(bars.Count - 1); double barLow = bars.GetLow(bars.Count - 1); int maxCompare = bars.Instrument.MasterInstrument.Compare(close, thisMax); int minCompare = bars.Instrument.MasterInstrument.Compare(close, thisMin); double thisClose = maxCompare > 0 ? Math.Min(close, thisMax) : minCompare < 0 ? Math.Max(close, thisMin) : close; // range exceeded; create new bar(s) if (maxCompare > 0 || minCompare < 0) { // local variables bool newBar = true; // update bias prevBias = thisBias; thisBias = close > barOpen ? 1 : close < barOpen ? -1 : 0; // close current bar; volume included for on-touch only // see this post for more info on volume calculation: http://www.ninjatrader.com/support/forum/showthread.php?p=302208#post302208 UpdateBar(bars, (maxCompare > 0 ? thisClose : barHigh), (minCompare < 0 ? thisClose : barLow), thisClose, time, 0); // add next bar and loop phantom bars, if needed do { // update thisRange for dynamic if (isDynamic) { // increment range for same bias, if range has not exceeded max if ((thisBias == prevBias || prevBias == 0) && thisRange < rangeMax) { thisRange = AddTwoDoubles(bars, thisRange, tickSize); } // increment range after trend change (will only fire once) else if (thisBias != prevBias && prevBias != 0) { thisRange = AddTwoDoubles(bars, rangeMin, tickSize); } // ensure valid range thisRange = Math.Min(thisRange, rangeMax); } // update fields AdjustMaxMin(bars, thisClose, close); thisClose = (maxCompare > 0) ? Math.Min(close, thisMax) : (minCompare < 0) ? Math.Max(close, thisMin) : close; // add new bar; include volume once (except for on-touch), then create phantom bars // see this post for more info on volume calculation: http://www.ninjatrader.com/support/forum/showthread.php?p=302208#post302208 AddBar(bars, thisOpen, (maxCompare > 0 ? thisClose : thisOpen), (minCompare < 0 ? thisClose : thisOpen), thisClose, time, (newBar ? volume : 0)); newBar = false; // update fields maxCompare = bars.Instrument.MasterInstrument.Compare(close, thisMax); minCompare = bars.Instrument.MasterInstrument.Compare(close, thisMin); }while (maxCompare > 0 || minCompare < 0); } else { UpdateBar(bars, (close > barHigh ? close : barHigh), (close < barLow ? close : barLow), close, time, volume); } } bars.LastPrice = close; }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { double lastBarClose = bars.GetClose(bars.Count - 1); // Trae el último precio de cierre if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } offset = bars.BarsPeriod.Value * bars.Instrument.MasterInstrument.TickSize; // Periocidad * tick (Tamaño de la caja) bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } // Si es una gráfica nueva o una sesión nueva y está en un nuevo día if (bars.Count == 0 || bars.IsResetOnNewTradingDay && isNewSession) { // una sesión nueva y está en un nuevo día if (bars.Count > 0) { // Close out last bar in session and set open == close DateTime lastBarTime = bars.GetTime(bars.Count - 1); // Trae la última fecha del precio de cierre long lastBarVolume = bars.GetVolume(bars.Count - 1); // Trae el último volumen de precio de cierre RemoveLastBar(bars); // Elimina la última barra AddBar(bars, lastBarClose, lastBarClose, lastBarClose, lastBarClose, lastBarTime, lastBarVolume); // Crea una nueva barra con la información obtenida } renkoHigh = close + offset; // Suma el valor de cierre y tamaño de la caja renkoLow = close - offset; // Diferencia del valor de cierre y el tamaño de la caja // ¿Hay un nuevo precio negociado? isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); // Entonces traiga el último precio } // Pinte el último precio negociado AddBar(bars, close, close, close, close, time, volume); bars.LastPrice = close; return; } double barOpen = bars.GetOpen(bars.Count - 1); // Obtiene el valor de apertura de la última barra double barHigh = bars.GetHigh(bars.Count - 1); // Obtiene el valor más alto negociado de la última barra double barLow = bars.GetLow(bars.Count - 1); // Obtiene el valor más bajo negociado de la última barra long barVolume = bars.GetVolume(bars.Count - 1); // Obtiene el volumen de la última barra DateTime barTime = bars.GetTime(bars.Count - 1); // Obtiene la fecha de la última barra // renkoHigh == 0 || renkoLow == 0 // ApproxCompare: Compares two double or float values for equality or being greater than / less than the compared to value. if (renkoHigh.ApproxCompare(0.0) == 0 || renkoLow.ApproxCompare(0.0) == 0) { if (bars.Count == 1) { renkoHigh = barOpen + offset; // suma = valor de apertura de la última barra + el tamaño de la caja renkoLow = barOpen - offset; // diferencia = valor de apertura de la última barra - el tamaño de la caja } // Penultimo valor de cierre es mayor al penultimo valor de apertura? else if (bars.GetClose(bars.Count - 2) > bars.GetOpen(bars.Count - 2)) { renkoHigh = bars.GetClose(bars.Count - 2) + offset; // Suma tamaño de la caja + el penultimo valor de cierre renkoLow = bars.GetClose(bars.Count - 2) - offset * 2; // Resta el doble del tamaño de la caja - el penultimo valor de cierre } else { renkoHigh = bars.GetClose(bars.Count - 2) + offset * 2; // Suma el doble tamaño de la caja + el penultimo valor de cierre renkoLow = bars.GetClose(bars.Count - 2) - offset; // Resta el tamaño de la caja - el penultimo valor de cierre } } bool isRail2Rail = false; // Hay cambio de tendencia hacia bajista? if (close <= (renkoHigh)) { // Elimina la barra de Update RemoveLastBar(bars); // Agrega la nueva barra con los nuevos valores renkoLow = renkoHigh - 2.0 * offset; // RenkoHigh - el doble del tamaño de la caja renkoHigh = renkoHigh + offset; // Renkohigh + el tamaño de la caja // Agrega barra alcista //AddBar(bars, _renkoLow - offset, Math.Max(_renkoLow - offset, _renkoLow), Math.Min(_renkoLow - offset, _renkoLow), _renkoLow, barTime, barVolume); //AddBar(bars, _renkoHigh + offset, Math.Max(_renkoHigh + offset, _renkoHigh), Math.Min(_renkoHigh + offset, _renkoHigh), _renkoHigh, barTime, barVolume); //AddBar(Bars bars, double open, double high, double low, double close, DateTime time, long volume) //Barra de una gráfica bajista AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, barTime, barVolume); isRail2Rail = true; } //bool isRail2Rail = false; // Hay cambio de tendencia hacia alcista? if (close >= (renkoLow)) { // Elimina la barra la barra de Update RemoveLastBar(bars); // Agrega la nueva barra con los nuevos valores // Original //AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, barTime, barVolume); // Bajista renkoHigh = renkoLow + 2.0 * offset; // RenkoLow - el doble del tamaño de la caja renkoLow = renkoLow - offset; // RenkoLow - el tamaño de la caja //AddBar(bars, _renkoHigh + offset, Math.Max(_renkoHigh + offset, _renkoHigh), Math.Min(_renkoHigh + offset, _renkoHigh), _renkoHigh, barTime, barVolume); //AddBar(bars, _renkoLow - offset, Math.Max(_renkoLow - offset, _renkoLow), Math.Min(_renkoLow - offset, _renkoLow), _renkoLow, barTime, barVolume); //Barra de gráfica alcista AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, barTime, barVolume); isRail2Rail = true; } // el precio de cierre es mayor renkohigh? // [DETECTA COMPORTAMIENTO ALCISTA] if (close.ApproxCompare(renkoHigh) >= 0) { /* if (trend != 0 && trend != 1) { * // Elimina la barra de Update * RemoveLastBar(bars); * * // Agrega la nueva barra con los nuevos valores * var _renkoLow = renkoHigh - 1.0 * offset; // RenkoHigh - el doble del tamaño de la caja * var _renkoHigh = renkoHigh + offset; // Renkohigh + el tamaño de la caja * // Agrega barra alcista * AddBar(bars, _renkoLow - offset, Math.Max(_renkoLow - offset, _renkoLow), Math.Min(_renkoLow - offset, _renkoLow), _renkoLow, barTime, barVolume); * * isRail2Rail = true; * } */ // (1) Obtiene el valor mayor entre renkoHigh y, renkoHigh - tamaño de la caja // (2) Si el valor de x es igual a y entonces retorna 0 // Si el valor de x es mayor a y entonces retorna 1 // Si el valor de x es menor a y entonces retorna -1 if (barOpen.ApproxCompare(renkoHigh - offset) != 0 || // valor de apertura de la (última barra - el tamño de la caja) es mayor o menor a barOpen? barHigh.ApproxCompare(Math.Max(renkoHigh - offset, renkoHigh)) != 0 || // Es barHigh mayor o menor a (1)? barLow.ApproxCompare(Math.Min(renkoHigh - offset, renkoHigh)) != 0) // Es barLow mayor o menor a (1)? { // No hubo cambio de tendencia if (!isRail2Rail) { // Elimina la última barra de Update RemoveLastBar(bars); } // Agrega una barra nueva con los nuevos valores // Alcista AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, barTime, barVolume); } renkoLow = renkoHigh - 2.0 * offset; // RenkoHigh - el doble del tamaño de la caja renkoHigh = renkoHigh + offset; // Renkohigh + el tamaño de la caja // ¿Hay un nuevo valor negociado? isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); // Obtiene el último valor negociado } // Agrega barras vacías para llenar el gap si el precio salta while (close.ApproxCompare(renkoHigh) >= 0) { AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, time, 0); renkoLow = renkoHigh - 2.0 * offset; renkoHigh = renkoHigh + offset; } // Agrega la barra final parcial AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, close), Math.Min(renkoHigh - offset, close), close, time, volume); trend = 1; } // el precio de cierre es menor o igual a renkohigh? // El precio de cierre es menor o igual al renkolow // [DETECTA COMPORTAMIENTO BAJISTA] else if (close.ApproxCompare(renkoLow) <= 0) { /* if (trend != 0 && trend != -1) { * // Elimina la barra la barra de Update * RemoveLastBar(bars); * // Agrega la nueva barra con los nuevos valores * // Original * //AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, barTime, barVolume); * // Bajista * var _renkoHigh = renkoLow + 1.0 * offset; // RenkoLow - el doble del tamaño de la caja * var _renkoLow = renkoLow - offset; // RenkoLow - el tamaño de la caja * AddBar(bars, _renkoHigh + offset, Math.Max(_renkoHigh + offset, _renkoHigh), Math.Min(_renkoHigh + offset, _renkoHigh), _renkoHigh, barTime, barVolume); * isRail2Rail = true; * } */ // (1) Obtiene el valor mayor entre renkoLow y, renkoLow + tamaño de la caja // (2) Si el valor de x es igual a y entonces retorna 0 // Si el valor de x es mayor a y entonces retorna 1 // Si el valor de x es menor a y entonces retorna -1 if (barOpen.ApproxCompare(renkoLow + offset) != 0 || // Valor de apertura de (renkolow + el tamaño de la caja) es mayor o menor a barOpen? barHigh.ApproxCompare(Math.Max(renkoLow + offset, renkoLow)) != 0 || // Es barHigh mayor o menor a (1)? barLow.ApproxCompare(Math.Min(renkoLow + offset, renkoLow)) != 0) // Es barlow mayor o menor a (1)? { // TODO: Validar si la condición cambia, si si, entonces no elimine la última barra if (!isRail2Rail) { // Elimine la barra de Update RemoveLastBar(bars); } // Agrega la nueva barra con los nuevos valores // AddBar(Bars bars, double open, double high, double low, double close, DateTime time, long volume) //Bajista AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, barTime, barVolume); } renkoHigh = renkoLow + 2.0 * offset; // RenkoLow - el doble del tamaño de la caja renkoLow = renkoLow - offset; // RenkoLow - el tamaño de la caja // ¿Hay un nuevo valor negociado? isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); // Obtiene el último valor negociado } // Agrega barras vacías para llenar el gap si el precio salta while (close.ApproxCompare(renkoLow) <= 0) { AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, time, 0); renkoHigh = renkoLow + 2.0 * offset; renkoLow = renkoLow - offset; } // Agrega la barra final parcial AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, close), Math.Min(renkoLow + offset, close), close, time, volume); trend = -1; } // El precio de cierre mayor al renkolow else { // Actualiza la barra UpdateBar(bars, close, close, close, time, volume); } // El último precio el valor de cierre bars.LastPrice = close; }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { Bars bars = chartBars.Bars; float chartMinX = ConvertToHorizontalPixels(chartControl, chartControl.CanvasLeft + chartControl.Properties.BarMarginRight); RectangleF rect = new RectangleF(); int toIndex = chartBars.ToIndex; if (toIndex >= 0 && toIndex < bars.Count - 1) { toIndex++; } for (int idx = chartBars.FromIndex; idx <= toIndex; idx++) { double closeValue = bars.GetClose(idx); float high = chartScale.GetYByValue(bars.GetHigh(idx)); float low = chartScale.GetYByValue(bars.GetLow(idx)); double openValue = bars.GetOpen(idx); Brush overriddenBarBrush = chartControl.GetBarOverrideBrush(chartBars, idx); Brush overriddenOutlineBrush = chartControl.GetCandleOutlineOverrideBrush(chartBars, idx); float x = chartControl.GetXByBarIndex(chartBars, idx); float boxStartPosition; if (idx == chartBars.FromIndex && (toIndex == 0 || idx == 0)) { if (toIndex == 0) { boxStartPosition = chartMinX; } else { boxStartPosition = 2 * x - chartControl.GetXByBarIndex(chartBars, idx + 1); } } else { boxStartPosition = chartControl.GetXByBarIndex(chartBars, idx - 1); } if (Math.Abs(x - boxStartPosition) < 0.2) { continue; } float width = Math.Max(2f, Math.Abs(x - boxStartPosition)); if (closeValue > openValue) { width -= Stroke.Width; rect.X = boxStartPosition; rect.Y = high; rect.Width = width; rect.Height = low - high; TransformBrush(overriddenBarBrush ?? UpBrushDX, rect); TransformBrush(overriddenOutlineBrush ?? Stroke.BrushDX, rect); RenderTarget.FillRectangle(rect, overriddenBarBrush ?? UpBrushDX); RenderTarget.DrawRectangle(rect, overriddenOutlineBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); } else { width -= Stroke2.Width; rect.X = boxStartPosition; rect.Y = high; rect.Width = width; rect.Height = low - high; TransformBrush(overriddenBarBrush ?? DownBrushDX, rect); TransformBrush(overriddenOutlineBrush ?? Stroke2.BrushDX, rect); RenderTarget.FillRectangle(rect, overriddenBarBrush ?? DownBrushDX); RenderTarget.DrawRectangle(rect, overriddenOutlineBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); } } }
/// <summary> /// </summary> /// <param name="bars"></param> /// <param name="open"></param> /// <param name="high"></param> /// <param name="low"></param> /// <param name="close"></param> /// <param name="time"></param> /// <param name="volume"></param> /// <param name="isRealtime"></param> public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { #region Building Bars from Base Period if (bars.Count != tmpCount) // reset cache when bars are trimmed if (bars.Count == 0) { tmpTime = Cbi.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; bars.LastPrice = anchorPrice = bars.GetClose(bars.Count - 1); } switch (bars.Period.BasePeriodType) { case PeriodType.Day: tmpTime = time.Date; if (isRealtime && time >= cacheSessionEnd) { tmpDayCount++; bars.Session.GetSessionDate(time, false, out tmpTime, out cacheSessionEnd); if (tmpTime < time.Date) tmpTime = time.Date; // make sure timestamps are ascending } if (!isRealtime && prevTimeD != tmpTime) tmpDayCount++; if ((!isRealtime && bars.Count > 0 && tmpTime == bars.TimeLastBar.Date) || (isRealtime && bars.Count > 0 && tmpTime <= bars.TimeLastBar.Date) || tmpDayCount < bars.Period.BasePeriodValue) endOfBar = false; else { prevTime = prevTimeD == Cbi.Globals.MinDate ? tmpTime : prevTimeD; prevTimeD = tmpTime; endOfBar = true; } break; case PeriodType.Minute: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); if (!isRealtime && time <= tmpTime || isRealtime && time < tmpTime) endOfBar = false; else { prevTime = tmpTime; tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); endOfBar = true; } break; case PeriodType.Volume: if (tmpTime == Cbi.Globals.MinDate) { tmpVolume = volume; endOfBar = tmpVolume >= bars.Period.BasePeriodValue; prevTime = tmpTime = time; if (endOfBar) tmpVolume = 0; break; } tmpVolume += volume; endOfBar = tmpVolume >= bars.Period.BasePeriodValue; if (endOfBar) { prevTime = tmpTime; tmpVolume = 0; tmpTime = time; } break; case PeriodType.Month: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); if (time.Month <= tmpTime.Month && time.Year == tmpTime.Year || time.Year < tmpTime.Year) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); } break; case PeriodType.Second: if (tmpTime == Cbi.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeSecond(bars, time, new DateTime(bars.Session.NextBeginTime.Year, bars.Session.NextBeginTime.Month, bars.Session.NextBeginTime.Day, bars.Session.NextBeginTime.Hour, bars.Session.NextBeginTime.Minute, 0), bars.Period.BasePeriodValue); } if (time <= tmpTime) endOfBar = false; else { prevTime = tmpTime; tmpTime = TimeToBarTimeSecond(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue); endOfBar = true; } break; case PeriodType.Tick: if (tmpTime == Cbi.Globals.MinDate || bars.Period.BasePeriodValue == 1) { prevTime = tmpTime = time; tmpTickCount = bars.Period.BasePeriodValue == 1 ? 0 : 1; endOfBar = bars.Period.BasePeriodValue == 1; break; } if (tmpTickCount < bars.Period.BasePeriodValue) { tmpTime = time; endOfBar = false; tmpTickCount++; } else { prevTime = tmpTime; tmpTime = time; endOfBar = true; tmpTickCount = 1; } break; case PeriodType.Week: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); if (time.Date <= tmpTime.Date) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); } break; case PeriodType.Year: if (tmpTime == Cbi.Globals.MinDate) prevTime = tmpTime = TimeToBarTimeYear(time, bars.Period.Value); if (time.Year <= tmpTime.Year) endOfBar = false; else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeYear(time, bars.Period.Value); } break; default: break; } #endregion #region P&F logic double tickSize = bars.Instrument.MasterInstrument.TickSize; boxSize = Math.Floor(10000000.0 * bars.Period.Value * tickSize) / 10000000.0; reversalSize = bars.Period.Value2 * boxSize; if (bars.Count == 0 || (IsIntraday && bars.IsNewSession(time, isRealtime))) { if (bars.Count > 0) { double lastOpen = bars.GetOpen(bars.Count - 1); double lastHigh = bars.GetHigh(bars.Count - 1); double lastLow = bars.GetLow(bars.Count - 1); double lastClose = bars.GetClose(bars.Count - 1); DateTime lastTime = bars.GetTime(bars.Count - 1); bars.LastPrice = anchorPrice = lastClose; if (bars.Count == tmpCount) CalculatePfBar(bars, lastOpen, lastHigh, lastLow, lastClose, prevTime, lastTime, isRealtime); } AddBar(bars, close, close, close, close, tmpTime, volume, isRealtime); anchorPrice = close; trend = Trend.Undetermined; prevTime = tmpTime; volumeCount = 0; bars.LastPrice = close; tmpCount = bars.Count; tmpHigh = high; tmpLow = low; return; } Bar bar = (Bar)bars.Get(bars.Count - 1); double c = bar.Close; double o = bar.Open; double h = bar.High; double l = bar.Low; DateTime t = bar.Time; if (endOfBar) { CalculatePfBar(bars, o, h, l, c, prevTime, t, isRealtime); volumeCount = volume; tmpHigh = high; tmpLow = low; } else { tmpHigh = (high > tmpHigh ? high : tmpHigh); tmpLow = (low < tmpLow ? low : tmpLow); volumeCount += volume; } bars.LastPrice = close; tmpCount = bars.Count; #endregion }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } double haClose = 0.0; double haHigh = 0.0; double haLow = 0.0; double haOpen = 0.0; switch (BarsPeriod.BaseBarsPeriodType) { case BarsPeriodType.Day: { if (bars.Count == 0) { if (isBar || bars.TradingHours.Sessions.Count == 0) { AddBar(bars, open, high, low, close, time.Date, volume); } else { SessionIterator.CalculateTradingDay(time, false); AddBar(bars, open, high, low, close, SessionIterator.ActualTradingDayExchange, volume); } } else { DateTime barTime; if (isBar) { barTime = time.Date; } else { if (bars.TradingHours.Sessions.Count > 0 && SessionIterator.IsNewSession(time, false)) { SessionIterator.CalculateTradingDay(time, false); barTime = SessionIterator.ActualTradingDayExchange; if (barTime < bars.LastBarTime.Date) { barTime = bars.LastBarTime.Date; // Make sure timestamps are ascending } } else { barTime = bars.LastBarTime.Date; // Make sure timestamps are ascending } } if (bars.DayCount < bars.BarsPeriod.BaseBarsPeriodValue || isBar && bars.Count > 0 && barTime == bars.LastBarTime.Date || !isBar && bars.Count > 0 && barTime <= bars.LastBarTime.Date) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, barTime, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, barTime, volume); } } break; } case BarsPeriodType.Minute: { if (bars.Count == 0) { AddBar(bars, open, high, low, close, TimeToBarTimeMinute(bars, time, isBar), volume); } else if (!isBar && time < bars.LastBarTime) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } else if (isBar && time <= bars.LastBarTime) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); time = TimeToBarTimeMinute(bars, time, isBar); AddBar(bars, haOpen, haHigh, haLow, haClose, time, volume); } break; } case BarsPeriodType.Month: { if (bars.Count == 0) { AddBar(bars, open, high, low, close, TimeToBarTimeMonth(time, bars.BarsPeriod.BaseBarsPeriodValue), volume); } else if (time.Month <= bars.LastBarTime.Month && time.Year == bars.LastBarTime.Year || time.Year < bars.LastBarTime.Year) { if (high.ApproxCompare(bars.GetHigh(bars.Count - 1)) != 0 || low.ApproxCompare(bars.GetLow(bars.Count - 1)) != 0 || close.ApproxCompare(bars.GetClose(bars.Count - 1)) != 0 || volume > 0) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, TimeToBarTimeMonth(time, bars.BarsPeriod.BaseBarsPeriodValue), volume); } break; } case BarsPeriodType.Second: { if (bars.Count == 0) { DateTime barTime = TimeToBarTimeSecond(bars, time, isBar); AddBar(bars, open, high, low, close, barTime, volume); } else { if (bars.BarsPeriod.BaseBarsPeriodValue > 1 && time < bars.LastBarTime || bars.BarsPeriod.BaseBarsPeriodValue == 1 && time <= bars.LastBarTime) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); time = TimeToBarTimeSecond(bars, time, isBar); AddBar(bars, haOpen, haHigh, haLow, haClose, time, volume); } } break; } case BarsPeriodType.Tick: { bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } if (bars.BarsPeriod.BaseBarsPeriodValue == 1) { haOpen = haOpen.ApproxCompare(0.0) == 0 ? open : (haOpen + haClose) / 2.0; haClose = haClose.ApproxCompare(0.0) == 0 ? close : bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, time, volume); } else if (bars.Count == 0) { AddBar(bars, open, high, low, close, time, volume); } else if (bars.Count > 0 && (!isNewSession || !bars.IsResetOnNewTradingDay) && bars.BarsPeriod.BaseBarsPeriodValue > 1 && bars.TickCount < bars.BarsPeriod.BaseBarsPeriodValue) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, time, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, time, volume); } break; } case BarsPeriodType.Volume: { if (bars.Count == 0) { while (volume > bars.BarsPeriod.BaseBarsPeriodValue) { haOpen = haOpen.ApproxCompare(0.0) == 0 ? open : (haOpen + haClose) / 2.0; haClose = haClose.ApproxCompare(0) == 0 ? close : bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, time, bars.BarsPeriod.BaseBarsPeriodValue); volume -= bars.BarsPeriod.BaseBarsPeriodValue; } if (volume > 0) { haOpen = haOpen.ApproxCompare(0.0) == 0 ? open : bars.Instrument.MasterInstrument.RoundToTickSize((haOpen + haClose) / 2.0); haClose = haClose.ApproxCompare(0.0) == 0 ? close : bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, time, volume); } } else { long volumeTmp = 0; bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (!bars.IsResetOnNewTradingDay || !isNewSession) { volumeTmp = Math.Min(bars.BarsPeriod.BaseBarsPeriodValue - bars.GetVolume(bars.Count - 1), volume); if (volumeTmp > 0) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, time, volumeTmp); } } if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } volumeTmp = volume - volumeTmp; while (volumeTmp > 0) { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, time, Math.Min(volumeTmp, bars.BarsPeriod.BaseBarsPeriodValue)); volumeTmp -= bars.BarsPeriod.BaseBarsPeriodValue; } } break; } case BarsPeriodType.Week: { if (bars.Count == 0) { AddBar(bars, open, high, low, close, TimeToBarTimeWeek(time, time.AddDays(6 - ((int)time.DayOfWeek + 1) % 7 + (bars.BarsPeriod.BaseBarsPeriodValue - 1) * 7), bars.BarsPeriod.BaseBarsPeriodValue), volume); } else if (time.Date <= bars.LastBarTime.Date) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, TimeToBarTimeWeek(time.Date, bars.LastBarTime.Date, bars.BarsPeriod.BaseBarsPeriodValue), volume); } break; } case BarsPeriodType.Year: { if (bars.Count == 0) { AddBar(bars, open, high, low, close, TimeToBarTimeYear(time, bars.BarsPeriod.BaseBarsPeriodValue), volume); } else { if (time.Year <= bars.LastBarTime.Year) { haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, bars.GetOpen(bars.Count - 1))); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, bars.GetOpen(bars.Count - 1))); UpdateBar(bars, haHigh, haLow, haClose, bars.LastBarTime, volume); } else { haOpen = bars.Instrument.MasterInstrument.RoundToTickSize((bars.GetOpen(bars.Count - 1) + bars.GetClose(bars.Count - 1)) / 2.0); haClose = bars.Instrument.MasterInstrument.RoundToTickSize((open + high + low + close) / 4.0); haHigh = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Max(high, haOpen)); haLow = bars.Instrument.MasterInstrument.RoundToTickSize(Math.Min(low, haOpen)); AddBar(bars, haOpen, haHigh, haLow, haClose, TimeToBarTimeYear(time.Date, bars.BarsPeriod.BaseBarsPeriodValue), volume); } } break; } } bars.LastPrice = haClose; }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { Bars bars = chartBars.Bars; float barWidth = GetBarPaintWidth(BarWidthUI); Vector2 point0 = new Vector2(); Vector2 point1 = new Vector2(); RectangleF rect = new RectangleF(); for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++) { Brush overriddenBarBrush = chartControl.GetBarOverrideBrush(chartBars, idx); Brush overriddenOutlineBrush = chartControl.GetCandleOutlineOverrideBrush(chartBars, idx); double closeValue = bars.GetClose(idx); int close = chartScale.GetYByValue(closeValue); int high = chartScale.GetYByValue(bars.GetHigh(idx)); int low = chartScale.GetYByValue(bars.GetLow(idx)); double openValue = bars.GetOpen(idx); int open = chartScale.GetYByValue(openValue); int x = chartControl.GetXByBarIndex(chartBars, idx); if (Math.Abs(open - close) < 0.0000001) { // Line point0.X = x - barWidth * 0.5f; point0.Y = close; point1.X = x + barWidth * 0.5f; point1.Y = close; Brush b = overriddenOutlineBrush ?? Stroke.BrushDX; if (!(b is SolidColorBrush)) { TransformBrush(overriddenOutlineBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); } RenderTarget.DrawLine(point0, point1, b, Stroke.Width, Stroke.StrokeStyle); } else { // Candle rect.X = x - barWidth * 0.5f + 0.5f; rect.Y = Math.Min(close, open); rect.Width = barWidth - 1; rect.Height = Math.Max(open, close) - Math.Min(close, open); Brush brush = overriddenBarBrush ?? (closeValue >= openValue ? UpBrushDX : DownBrushDX); if (!(brush is SolidColorBrush)) { TransformBrush(brush, rect); } RenderTarget.FillRectangle(rect, brush); brush = overriddenOutlineBrush ?? Stroke.BrushDX; if (!(brush is SolidColorBrush)) { TransformBrush(brush, rect); } RenderTarget.DrawRectangle(rect, overriddenOutlineBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); } Brush br = overriddenOutlineBrush ?? Stroke2.BrushDX; // High wick if (high < Math.Min(open, close)) { point0.X = x; point0.Y = high; point1.X = x; point1.Y = Math.Min(open, close); if (!(br is SolidColorBrush)) { TransformBrush(br, new RectangleF(point0.X - Stroke2.Width, point0.Y, Stroke2.Width, point1.Y - point0.Y)); } RenderTarget.DrawLine(point0, point1, br, Stroke2.Width, Stroke2.StrokeStyle); } // Low wick if (low > Math.Max(open, close)) { point0.X = x; point0.Y = low; point1.X = x; point1.Y = Math.Max(open, close); if (!(br is SolidColorBrush)) { TransformBrush(br, new RectangleF(point1.X - Stroke2.Width, point1.Y, Stroke2.Width, point0.Y - point1.Y)); } RenderTarget.DrawLine(point0, point1, br, Stroke2.Width, Stroke2.StrokeStyle); } } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { if (chartBars.FromIndex > chartBars.ToIndex) { return; } if (chartBars.FromIndex > 0) { chartBars.FromIndex--; } Bars bars = chartBars.Bars; float barWidth = GetBarPaintWidth(BarWidthUI); int sessionStartIndex = chartBars.FromIndex; int thickOffsetTop = (int)(Stroke.Width * 0.5); int thinOffsetTop = (int)(Stroke2.Width * 0.5); Vector2 point0 = new Vector2(); Vector2 point1 = new Vector2(); while (sessionStartIndex > 0 && bars.BarsType.IsIntraday) { if (bars.BarsSeries.GetIsFirstBarOfSession(sessionStartIndex)) { break; } sessionStartIndex--; } if (sessionStartIndex < 0) // Occurs when all bars are off screen { return; } thickLine = bars.GetClose(sessionStartIndex) > bars.GetOpen(sessionStartIndex); //Determine the next bar coming up is thick or thin for (int k = sessionStartIndex + 1; k < chartBars.FromIndex; k++) { double closeTest = bars.GetClose(k); if (closeTest > bars.GetOpen(k)) { if (Math.Max(bars.GetOpen(k - 1), bars.GetClose(k - 1)) < closeTest) { thickLine = true; } } else if (closeTest < Math.Min(bars.GetOpen(k - 1), bars.GetClose(k - 1))) { thickLine = false; } } for (int idx = chartBars.FromIndex; idx <= chartBars.ToIndex; idx++) { Brush overriddenBrush = chartControl.GetBarOverrideBrush(chartBars, idx); double openValue = bars.GetOpen(idx); float open = chartScale.GetYByValue(openValue); double closeValue = bars.GetClose(idx); float close = chartScale.GetYByValue(closeValue); float x = chartControl.GetXByBarIndex(chartBars, idx); double prevOpenValue = idx == 0 ? openValue : bars.GetOpen(idx - 1); double prevCloseValue = idx == 0 ? closeValue : bars.GetClose(idx - 1); float startPosition; if (idx == 0 && chartBars.ToIndex >= 1) { float x0 = chartControl.GetXByBarIndex(chartBars, 0); float x1 = chartControl.GetXByBarIndex(chartBars, 1); float diffX = Math.Max(1, x1 - x0); startPosition = x0 - diffX; } else { startPosition = idx == chartBars.FromIndex ? chartControl.GetXByBarIndex(chartBars, idx) : chartControl.GetXByBarIndex(chartBars, idx - 1); } startPosition = startPosition < 0 ? 0 : startPosition; if (bars.BarsType.IsIntraday && bars.IsResetOnNewTradingDay && bars.BarsSeries.GetIsFirstBarOfSession(idx)) { // First bar if (closeValue > openValue) { point0.X = x; point0.Y = open; point1.X = x; point1.Y = close; TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); thickLine = true; } else { point0.X = x; point0.Y = open; point1.X = x; point1.Y = close; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); thickLine = false; } } else { if (closeValue > openValue) { if (closeValue <= Math.Max(prevCloseValue, prevOpenValue)) { // Maintain previous thickness if (thickLine) { point0.X = x; point0.Y = open + thickOffsetTop; point1.X = x; point1.Y = close - thickOffsetTop; TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); } else { point0.X = x; point0.Y = open + thinOffsetTop; point1.X = x; point1.Y = close - thinOffsetTop; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); } } else if (closeValue > Math.Max(prevCloseValue, prevOpenValue)) { double transitionPoint = Math.Max(prevCloseValue, prevOpenValue); point0.X = x; point0.Y = close - thickOffsetTop; point1.X = x; point1.Y = chartScale.GetYByValue(transitionPoint); TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); point0.X = x; point0.Y = chartScale.GetYByValue(transitionPoint); point1.X = x; point1.Y = open + (thickLine ? thickOffsetTop : thinOffsetTop); TransformBrush(overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), new RectangleF(point0.X, point0.Y - (thickLine ? Stroke.Width : Stroke2.Width), barWidth, thickLine ? Stroke.Width : Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), thickLine ? Stroke.Width : Stroke2.Width, thickLine ? Stroke.StrokeStyle : Stroke2.StrokeStyle); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), new RectangleF(point0.X, point0.Y - (thickLine ? Stroke.Width : Stroke2.Width), barWidth, thickLine ? Stroke.Width : Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), thickLine ? Stroke.Width : Stroke2.Width, thickLine ? Stroke.StrokeStyle : Stroke2.StrokeStyle); thickLine = true; } } else { if (Math.Min(prevCloseValue, prevOpenValue) <= closeValue) { // Maintain previous thickness if (thickLine) { point0.X = x; point0.Y = open - thickOffsetTop; point1.X = x; point1.Y = close + thickOffsetTop; TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? Stroke.BrushDX, new RectangleF(point0.X, point0.Y - Stroke.Width, barWidth, Stroke.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke.BrushDX, Stroke.Width, Stroke.StrokeStyle); } else { point0.X = x; point0.Y = open - thinOffsetTop; point1.X = x; point1.Y = close + thinOffsetTop; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); } } else if (closeValue < Math.Min(prevCloseValue, prevOpenValue)) { double transitionPoint = Math.Min(prevCloseValue, prevOpenValue); point0.X = startPosition; point0.Y = open; point1.X = x; point1.Y = open; TransformBrush(overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), new RectangleF(point0.X, point0.Y - (thickLine ? Stroke.Width : Stroke2.Width), barWidth, thickLine ? Stroke.Width : Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), thickLine ? Stroke.Width : Stroke2.Width, thickLine ? Stroke.StrokeStyle : Stroke2.StrokeStyle); point0.X = x; point0.Y = open - (thickLine ? thickOffsetTop : thinOffsetTop); point1.X = x; point1.Y = chartScale.GetYByValue(transitionPoint); TransformBrush(overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), new RectangleF(point0.X, point0.Y - (thickLine ? Stroke.Width : Stroke2.Width), barWidth, thickLine ? Stroke.Width : Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? (thickLine ? Stroke.BrushDX : Stroke2.BrushDX), thickLine ? Stroke.Width : Stroke2.Width, thickLine ? Stroke.StrokeStyle : Stroke2.StrokeStyle); point0.X = x; point0.Y = chartScale.GetYByValue(transitionPoint); point1.X = x; point1.Y = close + thinOffsetTop; TransformBrush(overriddenBrush ?? Stroke2.BrushDX, new RectangleF(point0.X, point0.Y - Stroke2.Width, barWidth, Stroke2.Width)); RenderTarget.DrawLine(point0, point1, overriddenBrush ?? Stroke2.BrushDX, Stroke2.Width, Stroke2.StrokeStyle); thickLine = false; } } } } }
/// <summary> /// </summary> /// <param name="bars"></param> /// <param name="open"></param> /// <param name="high"></param> /// <param name="low"></param> /// <param name="close"></param> /// <param name="time"></param> /// <param name="volume"></param> /// <param name="isRealtime"></param> public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { offset = bars.Period.Value * bars.Instrument.MasterInstrument.TickSize; if (bars.Count < tmpCount && bars.Count > 0) // reset cache when bars are trimmed { renkoHigh = bars.GetClose(bars.Count - 1) + offset; renkoLow = bars.GetClose(bars.Count - 1) - offset; } if ((bars.Count == 0) || (bars.IsNewSession(time, isRealtime))) { if (bars.Count != 0) { // close out last bar in session and set open == close Bar lastBar = (Bar)bars.Get(bars.Count - 1); bars.RemoveLastBar(isRealtime); // Note: bar is now just a local var and not in series! AddBar(bars, lastBar.Close, lastBar.Close, lastBar.Close, lastBar.Close, lastBar.Time, lastBar.Volume, isRealtime); } renkoHigh = close + offset; renkoLow = close - offset; AddBar(bars, close, close, close, close, time, volume, isRealtime); bars.LastPrice = close; return; } Bar bar = (Bar)bars.Get(bars.Count - 1); if (renkoHigh == 0 || renkoLow == 0) //Not sure why, but happens { if (bars.Count == 1) { renkoHigh = bar.Open + offset; renkoLow = bar.Open - offset; } else if (bars.GetClose(bars.Count - 2) > bars.GetOpen(bars.Count - 2)) { renkoHigh = bars.GetClose(bars.Count - 2) + offset; renkoLow = bars.GetClose(bars.Count - 2) - offset * 2; } else { renkoHigh = bars.GetClose(bars.Count - 2) + offset * 2; renkoLow = bars.GetClose(bars.Count - 2) - offset; } } if (bars.Instrument.MasterInstrument.Compare(close, renkoHigh) >= 0) { if (bars.Instrument.MasterInstrument.Compare(bar.Open, renkoHigh - offset) != 0 || bars.Instrument.MasterInstrument.Compare(bar.High, Math.Max(renkoHigh - offset, renkoHigh)) != 0 || bars.Instrument.MasterInstrument.Compare(bar.Low, Math.Min(renkoHigh - offset, renkoHigh)) != 0) { bars.RemoveLastBar(isRealtime); // Note: bar is now just a local var and not in series! AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, time, bar.Volume + volume, isRealtime); } else UpdateBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, time, volume, isRealtime); renkoLow = renkoHigh - 2.0 * offset; renkoHigh = renkoHigh + offset; while (bars.Instrument.MasterInstrument.Compare(close, renkoHigh) >= 0) // add empty bars to fill gap { AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, time, 1, isRealtime); renkoLow = renkoHigh - 2.0 * offset; renkoHigh = renkoHigh + offset; } // add final partial bar AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, close), Math.Min(renkoHigh - offset, close), close, time, 1, isRealtime); } else if (bars.Instrument.MasterInstrument.Compare(close, renkoLow) <= 0) { if (bars.Instrument.MasterInstrument.Compare(bar.Open, renkoLow + offset) != 0 || bars.Instrument.MasterInstrument.Compare(bar.High, Math.Max(renkoLow + offset, renkoLow)) != 0 || bars.Instrument.MasterInstrument.Compare(bar.Low, Math.Min(renkoLow + offset, renkoLow)) != 0) { bars.RemoveLastBar(isRealtime); // Note: bar is now just a local var and not in series! AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, time, bar.Volume + volume, isRealtime); } else UpdateBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, time, volume, isRealtime); renkoHigh = renkoLow + 2.0 * offset; renkoLow = renkoLow - offset; while (bars.Instrument.MasterInstrument.Compare(close, renkoLow) <= 0) // add empty bars to fill gap { AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, time, 1, isRealtime); renkoHigh = renkoLow + 2.0 * offset; renkoLow = renkoLow - offset; } // add final partial bar AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, close), Math.Min(renkoLow + offset, close), close, time, 1, isRealtime); } else // Note: open does not really change UpdateBar(bars, close, close, close, close, time, volume, isRealtime); bars.LastPrice = close; tmpCount = bars.Count; }
public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { // ******************* ADDED FROM RENKO CODE TO SOLVE MEMORY LEAK **************************** // brick size is the trendOffset (Value) + openOffset (BasePeriodValue) offset = (bars.Period.Value + bars.Period.BasePeriodValue) * bars.Instrument.MasterInstrument.TickSize; if (bars.Count < tmpCount && bars.Count > 0) // reset cache when bars are trimmed { barMax = bars.GetClose(bars.Count - 1) + offset; barMin = bars.GetClose(bars.Count - 1) - offset; } // ******************************************************************************************** //### First Bar if ((bars.Count == 0) || bars.IsNewSession(time, isRealtime)) { tickSize = bars.Instrument.MasterInstrument.TickSize; //### Parse Long Param Specification if (bars.Period.Value >= 1000000) { int d; string str = bars.Period.Value.ToString("000000000"); d = 0; Int32.TryParse(str.Substring(0, 3), out d); bars.Period.Value = d; d = 0; Int32.TryParse(str.Substring(3, 3), out d); bars.Period.Value2 = d; d = 0; Int32.TryParse(str.Substring(6, 3), out d); bars.Period.BasePeriodValue = d; } //****** ADDED FROM RENKO ***************************************************************** if (bars.Count != 0) { // close out last bar in session and set open == close Bar lastBar = (Bar)bars.Get(bars.Count - 1); bars.RemoveLastBar(); // Note: bar is now just a local var and not in series! AddBar(bars, lastBar.Close, lastBar.High, lastBar.Low, lastBar.Close, lastBar.Time, lastBar.Volume, isRealtime); } //**************************************************************************************** trendOffset = bars.Period.Value * bars.Instrument.MasterInstrument.TickSize; reversalOffset = bars.Period.Value2 * bars.Instrument.MasterInstrument.TickSize; //bars.Period.BasePeriodValue = bars.Period.Value; //### Remove to customize OpenOffset openOffset = Math.Ceiling((double)bars.Period.BasePeriodValue * 1) * bars.Instrument.MasterInstrument.TickSize; barOpen = close; barMax = barOpen + (trendOffset * barDirection); barMin = barOpen - (trendOffset * barDirection); AddBar(bars, barOpen, barOpen, barOpen, barOpen, time, volume, isRealtime); } //### Subsequent Bars else { Data.Bar bar = (Bar)bars.Get(bars.Count - 1); // *************ADDED FROM RENKO CODE (to deal with '0' values at Market Replay) ************ if (barMax == 0 || barMin == 0) //Not sure why, but happens { // trendOffset was also '0', so need to reinitialize trendOffset = bars.Period.Value * bars.Instrument.MasterInstrument.TickSize; reversalOffset = bars.Period.Value2 * bars.Instrument.MasterInstrument.TickSize; openOffset = Math.Ceiling((double)bars.Period.BasePeriodValue * 1) * bars.Instrument.MasterInstrument.TickSize; if (bars.Count == 1) { barMax = bar.Open + trendOffset; barMin = bar.Open - trendOffset; } else if (bars.GetClose(bars.Count - 2) > bars.GetOpen(bars.Count - 2)) { barMax = bars.GetClose(bars.Count - 2) + trendOffset; barMin = bars.GetClose(bars.Count - 2) - trendOffset * 2; } else { barMax = bars.GetClose(bars.Count - 2) + trendOffset * 2; barMin = bars.GetClose(bars.Count - 2) - trendOffset; } } // ************************************************************************************************ maxExceeded = bars.Instrument.MasterInstrument.Compare(close, barMax) > 0 ? true : false; minExceeded = bars.Instrument.MasterInstrument.Compare(close, barMin) < 0 ? true : false; //### Defined Range Exceeded? if (maxExceeded || minExceeded) { double thisClose = maxExceeded ? Math.Min(close, barMax) : minExceeded?Math.Max(close, barMin) : close; // thisClose is the minimum of BarMax and close (maxExceeded) barDirection = maxExceeded ? 1 : minExceeded ? -1 : 0; fakeOpen = thisClose - (openOffset * barDirection); //### Fake Open is halfway down the bar //### Close Current Bar UpdateBar(bars, bar.Open, (maxExceeded ? thisClose : bar.High), (minExceeded ? thisClose : bar.Low), thisClose, time, volume, isRealtime); //### Add New Bar barOpen = close; barMax = thisClose + ((barDirection > 0 ? trendOffset : reversalOffset)); barMin = thisClose - ((barDirection > 0 ? reversalOffset : trendOffset)); AddBar(bars, fakeOpen, (maxExceeded ? thisClose : fakeOpen), (minExceeded ? thisClose : fakeOpen), thisClose, time, volume, isRealtime); } //### Current Bar Still Developing else { UpdateBar(bars, bar.Open, (close > bar.High ? close : bar.High), (close < bar.Low ? close : bar.Low), close, time, volume, isRealtime); } } bars.LastPrice = close; tmpCount = bars.Count; // ADDED FROM RENKO CODE }
/// <summary> /// /// </summary> /// <param name="bars"></param> /// <param name="open"></param> /// <param name="high"></param> /// <param name="low"></param> /// <param name="close"></param> /// <param name="time"></param> /// <param name="volume"></param> /// <param name="isRealtime"></param> public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { if (bars.Count == 0 && tmpTime != Cbi.Globals.MinDate) // reset caching when live request trimmed existing bars tmpTime = Cbi.Globals.MinDate; bool endOfBar = true; if (tmpTime == Cbi.Globals.MinDate) { tmpTime = time; tmpDayCount = 1; tmpTickCount = 1; } else if (bars.Count < tmpCount && bars.Count == 0) // reset cache when bars are trimmed { tmpTime = Cbi.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else if (bars.Count < tmpCount && bars.Count > 0) // reset cache when bars are trimmed { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; } switch (bars.Period.BasePeriodType) { case PeriodType.Day: { if (bars.Count == 0 || (bars.Count > 0 && (bars.TimeLastBar.Month < time.Month || bars.TimeLastBar.Year < time.Year))) { tmpTime = time.Date; bars.LastPrice = close; newSession = true; } else { tmpTime = time.Date; tmpVolume += volume; bars.LastPrice = close; tmpDayCount++; if (tmpDayCount < bars.Period.BasePeriodValue || (bars.Count > 0 && bars.TimeLastBar.Date == time.Date)) endOfBar = false; } break; } case PeriodType.Minute: { if (bars.Count == 0 || bars.IsNewSession(time, isRealtime)) { tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); newSession = true; tmpVolume = 0; } else { if (isRealtime && time < bars.TimeLastBar || !isRealtime && time <= bars.TimeLastBar) { tmpTime = bars.TimeLastBar; endOfBar = false; } else tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); tmpVolume += volume; } break; } case PeriodType.Month: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); if (bars.Count == 0) break; endOfBar = false; } else if ((time.Month <= tmpTime.Month && time.Year == tmpTime.Year) || time.Year < tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } case PeriodType.Second: { if (bars.IsNewSession(time, isRealtime)) { tmpTime = TimeToBarTimeSecond(bars, time, new DateTime(bars.Session.NextBeginTime.Year, bars.Session.NextBeginTime.Month, bars.Session.NextBeginTime.Day, bars.Session.NextBeginTime.Hour, bars.Session.NextBeginTime.Minute, 0), bars.Period.BasePeriodValue); if (bars.Count == 0) break; endOfBar = false; newSession = true; } else if (time <= tmpTime) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } else tmpTime = TimeToBarTimeSecond(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue); break; } case PeriodType.Tick: { if (bars.IsNewSession(time, isRealtime)) { newSession = true; tmpTime = time; tmpTickCount = 1; if (bars.Count == 0) break; endOfBar = false; } else if (bars.Period.BasePeriodValue > 1 && tmpTickCount < bars.Period.BasePeriodValue) { tmpTime = time; tmpVolume += volume; tmpTickCount++; bars.LastPrice = close; endOfBar = false; } else tmpTime = time; // there can't be a situation when new ticks go into old bar, this would mean peeking into future. Fixed in NT7B14 20100416 CH break; } case PeriodType.Volume: { if (bars.IsNewSession(time, isRealtime)) newSession = true; else if (bars.Count == 0 && volume > 0) break; else { tmpVolume += volume; if (tmpVolume < bars.Period.BasePeriodValue) { bars.LastPrice = close; endOfBar = false; } else if (tmpVolume == 0) endOfBar = false; } tmpTime = time; // there can't be a situation when new ticks go into old bar, this would mean peeking into future. Fixed in NT7B14 20100416 CH break; } case PeriodType.Week: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); if (bars.Count == 0) break; endOfBar = false; } else if (time.Date <= tmpTime.Date) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } case PeriodType.Year: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeYear(time, bars.Period.Value); if (bars.Count == 0) break; endOfBar = false; } else if (time.Year <= tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } default: break; } if (bars.Count == 0 || (newSession && IsIntraday)) { AddBar(bars, open, close, close, close, tmpTime, volume, isRealtime); upTrend = (open < close); newSessionIdx = bars.Count - 1; newSession = false; firstBarOfSession = true; anchorPrice = close; switchPrice = open; } else if (firstBarOfSession && endOfBar == false) { double prevOpen = bars.GetOpen(bars.Count - 1); bars.RemoveLastBar(isRealtime); AddBar(bars, prevOpen, close, close, close, tmpTime, tmpVolume, isRealtime); upTrend = (prevOpen < close); anchorPrice = close; } else { int breakCount = bars.Period.Value; Bar bar = (Bar)bars.Get(bars.Count - 1); double breakMax = double.MinValue; double breakMin = double.MaxValue; if (firstBarOfSession) { AddBar(bars, anchorPrice, close, close, close, tmpTime, volume, isRealtime); firstBarOfSession = false; tmpVolume = volume; tmpTime = Cbi.Globals.MinDate; return; } if (bars.Count - newSessionIdx - 1 < breakCount) breakCount = bars.Count - (newSessionIdx + 1); for (int k = 1; k <= breakCount; k++) { Bar tmp = (Bar)bars.Get(bars.Count - k - 1); breakMax = Math.Max(breakMax, tmp.Open); breakMax = Math.Max(breakMax, tmp.Close); breakMin = Math.Min(breakMin, tmp.Open); breakMin = Math.Min(breakMin, tmp.Close); } bars.LastPrice = close; if (upTrend) if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bar.Close, anchorPrice) > 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; adding = true; } else if (bars.Instrument.MasterInstrument.Compare(breakMin, bar.Close) > 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; upTrend = false; adding = true; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, volume, isRealtime); } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume, isRealtime); } } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume, isRealtime); } else if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bar.Close, anchorPrice) < 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; adding = true; } else if (bars.Instrument.MasterInstrument.Compare(breakMax, bar.Close) < 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; upTrend = true; adding = true; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, volume, isRealtime); } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume, isRealtime); } } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume, isRealtime); } } if (endOfBar) tmpTime = Cbi.Globals.MinDate; tmpCount = bars.Count; }
public override void Add(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isRealtime) { #region Reset cache if (bars.Count == 0 && tmpTime != Cbi.Globals.MinDate) // reset caching when live request trimmed existing bars { tmpTime = Cbi.Globals.MinDate; } bool endOfBar = true; if (tmpTime == Cbi.Globals.MinDate) { tmpTime = time; tmpDayCount = 1; tmpTickCount = 1; } else if (bars.Count < tmpCount && bars.Count == 0) // reset cache when bars are trimmed { tmpTime = Cbi.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else if (bars.Count < tmpCount && bars.Count > 0) // reset cache when bars are trimmed { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; } #endregion #region Switch Periods switch (bars.Period.BasePeriodType) { #region tick case PeriodType.Tick: { if (bars.IsNewSession(time, isRealtime)) { newSession = true; tmpTime = time; tmpTickCount = 1; if (bars.Count == 0) { break; } endOfBar = false; } else { if (bars.Period.BasePeriodValue > 1 && tmpTickCount < bars.Period.BasePeriodValue) { tmpTime = time; tmpVolume += volume; tmpTickCount++; bars.LastPrice = close; endOfBar = false; } else { tmpTime = time; // there can't be a situation when new ticks go into old bar, this would mean peeking into future. Fixed in NT7B14 20100416 CH } } break; } #endregion #region Volume case PeriodType.Volume: { if (bars.IsNewSession(time, isRealtime)) { newSession = true; } else if (bars.Count == 0 && volume > 0) { break; } else { tmpVolume += volume; if (tmpVolume < bars.Period.BasePeriodValue) { bars.LastPrice = close; endOfBar = false; } else if (tmpVolume == 0) { endOfBar = false; } } tmpTime = time; // there can't be a situation when new ticks go into old bar, this would mean peeking into future. Fixed in NT7B14 20100416 CH break; } #endregion #region Second case PeriodType.Second: { if (bars.IsNewSession(time, isRealtime)) { tmpTime = TimeToBarTimeSecond(bars, time, new DateTime(bars.Session.NextBeginTime.Year, bars.Session.NextBeginTime.Month, bars.Session.NextBeginTime.Day, bars.Session.NextBeginTime.Hour, bars.Session.NextBeginTime.Minute, 0), bars.Period.BasePeriodValue); if (bars.Count == 0) { break; } endOfBar = false; newSession = true; } else { if (time <= tmpTime) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } else { tmpTime = TimeToBarTimeSecond(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue); } } break; } #endregion #region Day case PeriodType.Day: { if (bars.Count == 0 || (bars.Count > 0 && (bars.TimeLastBar.Month < time.Month || bars.TimeLastBar.Year < time.Year))) { tmpTime = time.Date; bars.LastPrice = close; newSession = true; } else { tmpTime = time.Date; tmpVolume += volume; bars.LastPrice = close; tmpDayCount++; if (tmpDayCount < bars.Period.BasePeriodValue || (bars.Count > 0 && bars.TimeLastBar.Date == time.Date)) { endOfBar = false; } } break; } #endregion #region Minute case PeriodType.Minute: { if (bars.Count == 0 || bars.IsNewSession(time, isRealtime)) { tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); newSession = true; tmpVolume = 0; } else { if (isRealtime && time < bars.TimeLastBar || !isRealtime && time <= bars.TimeLastBar) { tmpTime = bars.TimeLastBar; endOfBar = false; } else { tmpTime = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.BasePeriodValue, isRealtime); } tmpVolume += volume; } break; } #endregion #region Week case PeriodType.Week: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, bars.Period.BasePeriodValue); if (bars.Count == 0) { break; } endOfBar = false; } else { if (time.Date <= tmpTime.Date) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } } break; } #endregion #region Month case PeriodType.Month: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeMonth(time, bars.Period.BasePeriodValue); if (bars.Count == 0) { break; } endOfBar = false; } else { if ((time.Month <= tmpTime.Month && time.Year == tmpTime.Year) || time.Year < tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } } break; } #endregion #region Year case PeriodType.Year: { if (tmpTime == Cbi.Globals.MinDate) { tmpTime = TimeToBarTimeYear(time, bars.Period.Value); if (bars.Count == 0) { break; } endOfBar = false; } else { if (time.Year <= tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } } break; } #endregion #region Default default: break; #endregion } #endregion #region Add bars if (bars.Count == 0 || (newSession && IsIntraday)) // Very first bar setup. { #region First bar AddBar(bars, open, close, close, close, tmpTime, volume, isRealtime); upTrend = (open < close); newSessionIdx = bars.Count - 1; newSession = false; firstBarOfSession = true; anchorPrice = close; switchPrice = open; tmpHigh = close; tmpLow = close; #endregion } else if (firstBarOfSession && endOfBar == false) { #region Start of subsiquent bars double prevOpen = bars.GetOpen(bars.Count - 1); bars.RemoveLastBar(isRealtime); AddBar(bars, prevOpen, close, close, close, tmpTime, tmpVolume, isRealtime); upTrend = (prevOpen < close); anchorPrice = close; #endregion } else { int breakCount = bars.Period.Value; Bar bar = (Bar)bars.Get(bars.Count - 1); double breakMax = double.MinValue; double breakMin = double.MaxValue; if (firstBarOfSession) { AddBar(bars, anchorPrice, close, close, close, tmpTime, volume, isRealtime); firstBarOfSession = false; tmpVolume = volume; tmpTime = Cbi.Globals.MinDate; return; } if (bars.Count - newSessionIdx - 1 < breakCount) { breakCount = bars.Count - (newSessionIdx + 1); } for (int k = 1; k <= breakCount; k++) { Bar tmp = (Bar)bars.Get(bars.Count - k - 1); breakMax = Math.Max(breakMax, tmp.Open); breakMax = Math.Max(breakMax, tmp.Close); breakMin = Math.Min(breakMin, tmp.Open); breakMin = Math.Min(breakMin, tmp.Close); } bars.LastPrice = close; if (upTrend) { #region Up trend if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bar.Close, anchorPrice) > 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; adding = true; tmpHigh = bar.Close; tmpLow = bar.Close; } else if (bars.Instrument.MasterInstrument.Compare(breakMin, bar.Close) > 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; upTrend = false; adding = true; tmpHigh = bar.Close; tmpLow = bar.Close; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, volume, isRealtime); } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, tmpVolume, isRealtime); } } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, tmpVolume, isRealtime); } #endregion } else { #region Down trend if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bar.Close, anchorPrice) < 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; adding = true; tmpHigh = bar.Close; tmpLow = bar.Close; } else if (bars.Instrument.MasterInstrument.Compare(breakMax, bar.Close) < 0) { anchorPrice = bar.Close; switchPrice = bar.Open; tmpVolume = volume; upTrend = true; adding = true; tmpHigh = bar.Close; tmpLow = bar.Close; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, volume, isRealtime); } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, tmpVolume, isRealtime); } } else { bars.RemoveLastBar(isRealtime); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); tmpHigh = Math.Max(tmpHigh, close); tmpLow = Math.Min(tmpLow, close); AddBar(bars, tmpOpen, tmpHigh, tmpLow, close, tmpTime, tmpVolume, isRealtime); } #endregion } } #endregion if (endOfBar) { tmpTime = Cbi.Globals.MinDate; } tmpCount = bars.Count; }
protected override void OnBarUpdate() { /* When working with multiple bar series objects it is important to understand the sequential order in which the * OnBarUpdate() method is triggered. The bars will always run with the primary first followed by the secondary and * so on. * * Important: Primary bars will always execute before the secondary bar series. * If a bar is timestamped as 12:00PM on the 5min bar series, the call order between the equally timestamped 12:00PM * bar on the 1min bar series is like this: * 12:00PM 5min * 12:00PM 1min * 12:01PM 1min * 12:02PM 1min * 12:03PM 1min * 12:04PM 1min * 12:05PM 5min * 12:05PM 1min * * When the OnBarUpdate() is called from the primary bar series (2000 ticks series in this example), do the following */ if (BarsInProgress == 0) { if (CurrentBar < BarsRequiredToTrade) { return; } //Print("Current Bar time=" + Bars.GetTime(CurrentBar).ToString("HHmmss")); // if the bar elapsed time span across 12 mid night DateTime t1 = Bars.GetTime(CurrentBar - 1); DateTime t2 = Bars.GetTime(CurrentBar); if (TimeSpan.Compare(t1.TimeOfDay, t2.TimeOfDay) > 0) { Print("EOD Session"); HandleEOD(); string resetString = "-1"; byte[] resetMsg = Encoding.UTF8.GetBytes(resetString); // Send reset string of "-1" to the server int resetSent = sender.Send(resetMsg); lineNo = 0; //reset global flags currPos = Position.posFlat; profitChasingFlag = false; stopLossEncountered = false; return; } // prior Stop-Loss observed, construct the lineNo with special code before sending msg to the server - so that the server will flatten the position if (stopLossEncountered) { lineNo += 10000; } // construct the string buffer to be sent to DLNN string bufString = lineNo.ToString() + ',' + Bars.GetTime(CurrentBar - 1).ToString("HHmmss") + ',' + Bars.GetTime(CurrentBar).ToString("HHmmss") + ',' + Bars.GetOpen(CurrentBar).ToString() + ',' + Bars.GetClose(CurrentBar).ToString() + ',' + Bars.GetHigh(CurrentBar).ToString() + ',' + Bars.GetLow(CurrentBar).ToString() + ',' + Bars.GetVolume(CurrentBar).ToString() + ',' + SMA(9)[0].ToString() + ',' + SMA(20)[0].ToString() + ',' + SMA(50)[0].ToString() + ',' + MACD(12, 26, 9).Diff[0].ToString() + ',' + RSI(14, 3)[0].ToString() + ',' + Bollinger(2, 20).Lower[0].ToString() + ',' + Bollinger(2, 20).Upper[0].ToString() + ',' + CCI(20)[0].ToString() + ',' + Bars.GetHigh(CurrentBar).ToString() + ',' + Bars.GetLow(CurrentBar).ToString() + ',' + Momentum(20)[0].ToString() + ',' + DM(14).DiPlus[0].ToString() + ',' + DM(14).DiMinus[0].ToString() + ',' + VROC(25, 3)[0].ToString() + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0' + ',' + '0'; //Print("CurrentBar = " + CurrentBar + ": " + "bufString = " + bufString); byte[] msg = Encoding.UTF8.GetBytes(bufString); // Send the data through the socket. int bytesSent = sender.Send(msg); // Receive the response from the remote device. int bytesRec = sender.Receive(bytes); // prior Stop-Loss observed, hence ignore the returned signal from server and move on to the next bar, reset lineNo to next counter and reset stopLossEncountered flag if (stopLossEncountered) { lineNo -= 10000; lineNo++; stopLossEncountered = false; //svrSignal = ExtractResponse(System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length)); svrSignal = System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length).Split(',')[1]; Print(Bars.GetTime(CurrentBar).ToString("yyyy-MM-ddTHH:mm:ss.ffffffK") + " Ignore Post STOP-LOSS Server response= <" + svrSignal + "> Current Bar: Open=" + Bars.GetOpen(CurrentBar) + " Close=" + Bars.GetClose(CurrentBar) + " High=" + Bars.GetHigh(CurrentBar) + " Low=" + Bars.GetLow(CurrentBar)); return; } //svrSignal = ExtractResponse(System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length)); svrSignal = System.Text.Encoding.UTF8.GetString(bytes, 0, bytes.Length).Split(',')[1]; Print(Bars.GetTime(CurrentBar).ToString("yyyy-MM-ddTHH:mm:ss.ffffffK") + " Server response= <" + svrSignal + "> Current Bar: Open=" + Bars.GetOpen(CurrentBar) + " Close=" + Bars.GetClose(CurrentBar) + " High=" + Bars.GetHigh(CurrentBar) + " Low=" + Bars.GetLow(CurrentBar)); //Print(Bars.GetTime(CurrentBar).ToString("yyyy-MM-ddTHH:mm:ss.ffffffK") + " Server response= <" + svrSignal + ">"); // Return signal from DLNN is not we expected, close outstanding position and restart if (bytesRec == -1) { lineNo = 0; // TODO: close current position? } else { lineNo++; } // Start processing signal after 8th signal and beyond, otherwise ignore if (lineNo >= 8) { ExecuteAITrade(svrSignal); // if position is flat, no need to do anything if (currPos == Position.posFlat) { return; } // handle stop loss or profit chasing if there is existing position and order action is either SellShort or Buy if (entryOrder != null && (entryOrder.OrderAction == OrderAction.Buy || entryOrder.OrderAction == OrderAction.SellShort) && (entryOrder.OrderState == OrderState.Filled || entryOrder.OrderState == OrderState.PartFilled)) { // if Close[0] violates soft deck, if YES handle stop loss accordingly if (ViolateSoftDeck()) { HandleSoftDeck(svrSignal); } // if profitChasingFlag is TRUE or TouchedProfitChasing then handle profit chasing if ((profitChasingFlag || TouchedProfitChasing())) { HandleProfitChasing(); } } } } // When the OnBarUpdate() is called from the secondary bar series, in our case for each tick, handle stop loss and profit chasing accordingly else { return; } }
private void printAuswertung() { decimal GapTradeResult; Color colorTextBox; string strResultDescr = ""; GapTradeResult = (decimal)Bars.GetClose(ProcessingBarIndex - 1) - (decimal)Bars.GetOpen(ProcessingBarIndex - 1); if (GapTradeLong == true) { //Long GapTradeCounterLong += 1; GapTradeResultTotalLong = GapTradeResultTotalLong + GapTradeResult; string strGapeTradeLong = "GapTradeLong" + ProcessingBarIndex; string strTradeResultLong; TradeDir = "Long"; if (GapTradeResult < 0) { if (_print_info == true) { Print("Fail"); } GapTradeFailCounterLong += 1; strResultDescr = "Fail"; strTradeResultLong = "Fail " + GapTradeResult.ToString(); colorTextBox = colFail; } else { GapTradeWinCounterLong += 1; strResultDescr = "Win"; strTradeResultLong = "Win " + GapTradeResult.ToString(); colorTextBox = colWin; } AddChartText(strGapeTradeLong, true, strTradeResultLong, Time[1], Bars.GetHigh(ProcessingBarIndex - 1) + (100 * TickSize), 9, Color.Black, new Font("Arial", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } else if (GapTradeShort == true) { //Short GapTradeCounterShort += 1; GapTradeResultTotalShort = GapTradeResultTotalShort + GapTradeResult; string strGapeTradeShort = "GapTradeLong" + ProcessingBarIndex; string strTradeResultShort; TradeDir = "Short"; if (GapTradeResult > 0) { if (_print_info == true) { Print("Fail"); } GapTradeFailCounterShort += 1; strResultDescr = "Fail"; strTradeResultShort = "Fail " + GapTradeResult.ToString(); colorTextBox = colFail; } else { GapTradeWinCounterShort += 1; strResultDescr = "Win"; strTradeResultShort = "Win " + GapTradeResult.ToString(); colorTextBox = colWin; } AddChartText(strGapeTradeShort, true, strTradeResultShort, Time[1], Bars.GetLow(ProcessingBarIndex - 1) - (100 * TickSize), 9, Color.Black, new Font("Arial", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } if (_print_info == true) { Print("Gap Trade Result: " + GapTradeResult); } if (dev_mode == true) { Print(Instrument.Name + ";" + Math.Round(GapSize, 2) + ";" + GapTradeResult + ";" + strResultDescr + ";" + TradeDir); } }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } if (bars.Count == 0 && tmpTime != Core.Globals.MinDate) // Reset caching when live request trimmed existing bars { tmpTime = Core.Globals.MinDate; } bool endOfBar = true; if (tmpTime == Core.Globals.MinDate) { tmpTime = time; tmpDayCount = 1; tmpTickCount = 1; } else if (bars.Count < tmpCount && bars.Count == 0) // Reset cache when bars are trimmed { tmpTime = Core.Globals.MinDate; tmpVolume = 0; tmpDayCount = 0; tmpTickCount = 0; } else if (bars.Count < tmpCount && bars.Count > 0) // Reset cache when bars are trimmed { tmpTime = bars.GetTime(bars.Count - 1); tmpVolume = bars.GetVolume(bars.Count - 1); tmpTickCount = bars.TickCount; tmpDayCount = bars.DayCount; } switch (BarsPeriod.BaseBarsPeriodType) { case BarsPeriodType.Day: { if (bars.Count == 0 || bars.Count > 0 && (bars.LastBarTime.Month < time.Month || bars.LastBarTime.Year < time.Year)) { tmpTime = time.Date; bars.LastPrice = close; newSession = true; } else { tmpTime = time.Date; tmpVolume += volume; bars.LastPrice = close; tmpDayCount++; if (tmpDayCount < BarsPeriod.BaseBarsPeriodValue || bars.Count > 0 && bars.LastBarTime.Date == time.Date) { endOfBar = false; } } break; } case BarsPeriodType.Minute: { if (bars.Count == 0 || SessionIterator.IsNewSession(time, isBar) && bars.IsResetOnNewTradingDay) { tmpTime = TimeToBarTimeMinute(bars, time, isBar); newSession = true; tmpVolume = 0; } else { if (!isBar && time < bars.LastBarTime || isBar && time <= bars.LastBarTime) { tmpTime = bars.LastBarTime; endOfBar = false; } else { tmpTime = TimeToBarTimeMinute(bars, time, isBar); } tmpVolume += volume; } break; } case BarsPeriodType.Month: { if (tmpTime == Core.Globals.MinDate) { tmpTime = TimeToBarTimeMonth(time, BarsPeriod.BaseBarsPeriodValue); if (bars.Count == 0) { break; } endOfBar = false; } else if (time.Month <= tmpTime.Month && time.Year == tmpTime.Year || time.Year < tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } case BarsPeriodType.Second: { if (SessionIterator.IsNewSession(time, isBar)) { tmpTime = TimeToBarTimeSecond(bars, time, isBar); if (bars.Count == 0) { break; } endOfBar = false; newSession = true; } else if (time <= tmpTime) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } else { tmpTime = TimeToBarTimeSecond(bars, time, isBar); } break; } case BarsPeriodType.Tick: { if (SessionIterator.IsNewSession(time, isBar)) { SessionIterator.GetNextSession(time, isBar); newSession = true; tmpTime = time; tmpTickCount = 1; if (bars.Count == 0) { break; } endOfBar = false; } else if (BarsPeriod.BaseBarsPeriodValue > 1 && tmpTickCount < BarsPeriod.BaseBarsPeriodValue) { tmpTime = time; tmpVolume += volume; tmpTickCount++; bars.LastPrice = close; endOfBar = false; } else { tmpTime = time; } break; } case BarsPeriodType.Volume: { if (SessionIterator.IsNewSession(time, isBar)) { SessionIterator.GetNextSession(time, isBar); newSession = true; } else if (bars.Count == 0 && volume > 0) { break; } else { tmpVolume += volume; if (tmpVolume < BarsPeriod.BaseBarsPeriodValue) { bars.LastPrice = close; endOfBar = false; } else if (tmpVolume == 0) { endOfBar = false; } } tmpTime = time; break; } case BarsPeriodType.Week: { if (tmpTime == Core.Globals.MinDate) { tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, BarsPeriod.BaseBarsPeriodValue); if (bars.Count == 0) { break; } endOfBar = false; } else if (time.Date <= tmpTime.Date) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } case BarsPeriodType.Year: { if (tmpTime == Core.Globals.MinDate) { tmpTime = TimeToBarTimeYear(time, BarsPeriod.BaseBarsPeriodValue); if (bars.Count == 0) { break; } endOfBar = false; } else if (time.Year <= tmpTime.Year) { tmpVolume += volume; bars.LastPrice = close; endOfBar = false; } break; } } if (bars.Count > 0 && tmpTime < bars.GetTime(bars.Count - 1) && BarsPeriod.BaseBarsPeriodType == BarsPeriodType.Second) { tmpTime = bars.GetTime(bars.Count - 1); } if (bars.Count == 0 || newSession && IsIntraday) { AddBar(bars, open, close, close, close, tmpTime, volume); upTrend = open < close; newSessionIdx = bars.Count - 1; newSession = false; firstBarOfSession = true; anchorPrice = close; switchPrice = open; } else if (firstBarOfSession && endOfBar == false) { double prevOpen = bars.GetOpen(bars.Count - 1); RemoveLastBar(bars); if (SessionIterator.IsNewSession(tmpTime, true)) { SessionIterator.GetNextSession(tmpTime, true); } AddBar(bars, prevOpen, close, close, close, tmpTime, tmpVolume); upTrend = prevOpen < close; anchorPrice = close; } else { int breakCount = BarsPeriod.Value; double breakMax = double.MinValue; double breakMin = double.MaxValue; if (firstBarOfSession) { AddBar(bars, anchorPrice, close, close, close, tmpTime, volume); firstBarOfSession = false; tmpVolume = volume; tmpTime = Core.Globals.MinDate; return; } if (bars.Count - newSessionIdx - 1 < breakCount) { breakCount = bars.Count - (newSessionIdx + 1); } for (int k = 1; k <= breakCount; k++) { breakMax = Math.Max(breakMax, bars.GetOpen(bars.Count - k - 1)); breakMax = Math.Max(breakMax, bars.GetClose(bars.Count - k - 1)); breakMin = Math.Min(breakMin, bars.GetOpen(bars.Count - k - 1)); breakMin = Math.Min(breakMin, bars.GetClose(bars.Count - k - 1)); } bars.LastPrice = close; if (upTrend) { if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bars.GetClose(bars.Count - 1), anchorPrice) > 0) { anchorPrice = bars.GetClose(bars.Count - 1); switchPrice = bars.GetOpen(bars.Count - 1); tmpVolume = volume; adding = true; } else if (bars.Instrument.MasterInstrument.Compare(breakMin, bars.GetClose(bars.Count - 1)) > 0) { anchorPrice = bars.GetClose(bars.Count - 1); switchPrice = bars.GetOpen(bars.Count - 1); tmpVolume = volume; upTrend = false; adding = true; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, volume); } else { RemoveLastBar(bars); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); if (SessionIterator.IsNewSession(tmpTime, true)) { SessionIterator.GetNextSession(tmpTime, true); } AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume); } } else { RemoveLastBar(bars); double tmpOpen = Math.Min(Math.Max(switchPrice, close), anchorPrice); if (SessionIterator.IsNewSession(tmpTime, true)) { SessionIterator.GetNextSession(tmpTime, true); } AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume); } } else if (endOfBar) { bool adding = false; if (bars.Instrument.MasterInstrument.Compare(bars.GetClose(bars.Count - 1), anchorPrice) < 0) { anchorPrice = bars.GetClose(bars.Count - 1); switchPrice = bars.GetOpen(bars.Count - 1); tmpVolume = volume; adding = true; } else if (bars.Instrument.MasterInstrument.Compare(breakMax, bars.GetClose(bars.Count - 1)) < 0) { anchorPrice = bars.GetClose(bars.Count - 1); switchPrice = bars.GetOpen(bars.Count - 1); tmpVolume = volume; upTrend = true; adding = true; } if (adding) { double tmpOpen = upTrend ? Math.Min(Math.Max(switchPrice, close), anchorPrice) : Math.Max(Math.Min(switchPrice, close), anchorPrice); AddBar(bars, tmpOpen, close, close, close, tmpTime, volume); } else { RemoveLastBar(bars); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); if (SessionIterator.IsNewSession(tmpTime, true)) { SessionIterator.GetNextSession(tmpTime, true); } AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume); } } else { RemoveLastBar(bars); double tmpOpen = Math.Max(Math.Min(switchPrice, close), anchorPrice); if (SessionIterator.IsNewSession(tmpTime, true)) { SessionIterator.GetNextSession(tmpTime, true); } AddBar(bars, tmpOpen, close, close, close, tmpTime, tmpVolume); } } if (endOfBar) { tmpTime = Core.Globals.MinDate; } tmpCount = bars.Count; }
/// <summary> /// Called when the indicator is plotted. /// </summary> public override void Plot(Graphics graphics, Rectangle bounds, double min, double max) { int lastBar = Math.Min(this.LastBarIndexPainted, Bars.Count - 1); int barsPainted = ChartControl.BarsPainted; int firstBar = this.FirstBarIndexPainted; // Find highest and lowest price points double highPrice = 0; double lowPrice = double.MaxValue; for (int idx = firstBar; idx <= lastBar && idx >= 0; idx++) { highPrice = Math.Max(highPrice, Bars.GetHigh(idx)); lowPrice = Math.Min(lowPrice, Bars.GetLow(idx)); } int volumeBarCount = this.BarCount; double priceRange = highPrice - lowPrice; double priceBoxSize = priceRange / volumeBarCount; double volumeMax = 0; // Pass 1: Fill all VolumeInfo structures with appropriate data for (int i = 0; i < volumeBarCount; i++) { double priceUpper = lowPrice + priceBoxSize * (i + 1); double priceLower = lowPrice + priceBoxSize * i; double priceVolumeUp = 0; double priceVolumeDown = 0; for (int idx = firstBar; idx <= lastBar; idx++) { double checkPrice; switch (PriceType) { case PriceType.Open: checkPrice = Bars.GetOpen(idx); break; case PriceType.Close: checkPrice = Bars.GetClose(idx); break; case PriceType.High: checkPrice = Bars.GetHigh(idx); break; case PriceType.Low: checkPrice = Bars.GetLow(idx); break; case PriceType.Median: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx)) / 2; break; case PriceType.Typical: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + Bars.GetClose(idx)) / 3; break; case PriceType.Weighted: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + 2 * Bars.GetClose(idx)) / 4; break; default: checkPrice = Bars.GetClose(idx); break; } if (checkPrice >= priceLower && checkPrice < priceUpper) { if (Bars.GetOpen(idx) < Bars.GetClose(idx)) { priceVolumeUp += Bars.GetVolume(idx); } else { priceVolumeDown += Bars.GetVolume(idx); } } } volumeInfo[i].up = priceVolumeUp; volumeInfo[i].down = priceVolumeDown; volumeInfo[i].total = (double)priceVolumeUp + (double)priceVolumeDown; volumeMax = Math.Max(volumeMax, volumeInfo[i].total); } // Pass 2: Paint the volume bars for (int i = 0; i < Math.Min(volumeBarCount, lastBar - firstBar + 1); i++) { double priceUpper = lowPrice + priceBoxSize * (i + 1); double priceLower = lowPrice + priceBoxSize * i; int yUpper = GetYPos(priceUpper, bounds, min, max) + barSpacing; int yLower = GetYPos(priceLower, bounds, min, max); int barWidthUp = (int)((bounds.Width / 2) * (volumeInfo[i].up / volumeMax)); int barWidthDown = (int)((bounds.Width / 2) * (volumeInfo[i].down / volumeMax)); if (barWidthDown == int.MinValue || barWidthUp == int.MinValue) // overflow? { continue; } int barWidth = barWidthUp + barWidthDown; graphics.FillRectangle(barBrushUp, new Rectangle( bounds.X, yUpper, barWidthUp, Math.Abs(yUpper - yLower))); graphics.FillRectangle(barBrushDown, new Rectangle( bounds.X + barWidthUp, yUpper, barWidthDown, Math.Abs(yUpper - yLower))); if (drawLines == true) { // Lower line graphics.DrawLine(linePen, bounds.X, yLower, bounds.X + bounds.Width, yLower); // Upper line (only at the very top) if (i == volumeBarCount - 1) { graphics.DrawLine(linePen, bounds.X, yUpper, bounds.X + bounds.Width, yUpper); } } } }
protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (IsInHitTest) { return; } int lastBar = ChartBars.ToIndex; int firstBar = ChartBars.FromIndex; double highPrice = 0; double lowPrice = double.MaxValue; SharpDX.Direct2D1.Brush brushDown = BarDownBrush.ToDxBrush(RenderTarget); SharpDX.Direct2D1.Brush lineBrush = LineBrush.ToDxBrush(RenderTarget); SharpDX.Direct2D1.Brush brushUp = BarUpBrush.ToDxBrush(RenderTarget); brushDown.Opacity = (float)(Opacity / 100.0); brushUp.Opacity = (float)(Opacity / 100.0); for (int idx = firstBar; idx <= lastBar && idx >= 0; idx++) { highPrice = Math.Max(highPrice, Bars.GetHigh(idx)); lowPrice = Math.Min(lowPrice, Bars.GetLow(idx)); } int volumeBarCount = BarCount; double priceRange = highPrice - lowPrice; double priceBoxSize = priceRange / volumeBarCount; double volumeMax = 0; // Pass 1: Fill all VolumeInfo structures with appropriate data for (int i = 0; i < volumeBarCount; i++) { double priceUpper = lowPrice + priceBoxSize * (i + 1); double priceLower = lowPrice + priceBoxSize * i; double priceVolumeUp = 0; double priceVolumeDown = 0; for (int idx = firstBar; idx <= lastBar; idx++) { double checkPrice; PriceSeries series = (Inputs[0] as PriceSeries); switch (series.PriceType) { case PriceType.Open: checkPrice = Bars.GetOpen(idx); break; case PriceType.Close: checkPrice = Bars.GetClose(idx); break; case PriceType.High: checkPrice = Bars.GetHigh(idx); break; case PriceType.Low: checkPrice = Bars.GetLow(idx); break; case PriceType.Median: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx)) / 2; break; case PriceType.Typical: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + Bars.GetClose(idx)) / 3; break; case PriceType.Weighted: checkPrice = (Bars.GetHigh(idx) + Bars.GetLow(idx) + 2 * Bars.GetClose(idx)) / 4; break; default: checkPrice = Bars.GetClose(idx); break; } if (checkPrice >= priceLower && checkPrice < priceUpper) { if (Bars.GetOpen(idx) < Bars.GetClose(idx)) { priceVolumeUp += Bars.GetVolume(idx); } else { priceVolumeDown += Bars.GetVolume(idx); } } } volumeInfo[i].up = priceVolumeUp; volumeInfo[i].down = priceVolumeDown; volumeInfo[i].total = priceVolumeUp + priceVolumeDown; volumeMax = Math.Max(volumeMax, volumeInfo[i].total); } // Pass 2: Paint the volume bars for (int i = 0; i < Math.Min(volumeBarCount, lastBar - firstBar + 1); i++) { double priceUpper = lowPrice + priceBoxSize * (i + 1); double priceLower = lowPrice + priceBoxSize * i; int yUpper = Convert.ToInt32(chartScale.GetYByValue(priceUpper)) + BarSpacing; int yLower = Convert.ToInt32(chartScale.GetYByValue(priceLower)); int barWidthUp = (int)((chartScale.Height / 2) * (volumeInfo[i].up / volumeMax)); int barWidthDown = (int)((chartScale.Height / 2) * (volumeInfo[i].down / volumeMax)); SharpDX.RectangleF rect = new SharpDX.RectangleF(ChartPanel.X, yUpper, barWidthUp, Math.Abs(yUpper - yLower)); RenderTarget.FillRectangle(rect, brushUp); RenderTarget.DrawRectangle(rect, brushUp); SharpDX.RectangleF rect2 = new SharpDX.RectangleF(ChartPanel.X + barWidthUp, yUpper, barWidthDown, Math.Abs(yUpper - yLower)); RenderTarget.DrawRectangle(rect2, brushDown); RenderTarget.FillRectangle(rect2, brushDown); if (DrawLines) { RenderTarget.DrawLine(new SharpDX.Vector2(ChartPanel.X, yLower), new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, yLower), lineBrush); if (i == volumeBarCount - 1) { RenderTarget.DrawLine(new SharpDX.Vector2(ChartPanel.X, yUpper), new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, yUpper), lineBrush); } } } lineBrush.Dispose(); brushDown.Dispose(); brushUp.Dispose(); }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } offset = bars.BarsPeriod.Value * bars.Instrument.MasterInstrument.TickSize; bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } if (bars.Count == 0 || bars.IsResetOnNewTradingDay && isNewSession) { if (bars.Count > 0) { // Close out last bar in session and set open == close double lastBarClose = bars.GetClose(bars.Count - 1); DateTime lastBarTime = bars.GetTime(bars.Count - 1); long lastBarVolume = bars.GetVolume(bars.Count - 1); RemoveLastBar(bars); AddBar(bars, lastBarClose, lastBarClose, lastBarClose, lastBarClose, lastBarTime, lastBarVolume); } renkoHigh = close + offset; renkoLow = close - offset; isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } AddBar(bars, close, close, close, close, time, volume); bars.LastPrice = close; return; } double barOpen = bars.GetOpen(bars.Count - 1); double barHigh = bars.GetHigh(bars.Count - 1); double barLow = bars.GetLow(bars.Count - 1); long barVolume = bars.GetVolume(bars.Count - 1); DateTime barTime = bars.GetTime(bars.Count - 1); if (renkoHigh.ApproxCompare(0.0) == 0 || renkoLow.ApproxCompare(0.0) == 0) { if (bars.Count == 1) { renkoHigh = barOpen + offset; renkoLow = barOpen - offset; } else if (bars.GetClose(bars.Count - 2) > bars.GetOpen(bars.Count - 2)) { renkoHigh = bars.GetClose(bars.Count - 2) + offset; renkoLow = bars.GetClose(bars.Count - 2) - offset * 2; } else { renkoHigh = bars.GetClose(bars.Count - 2) + offset * 2; renkoLow = bars.GetClose(bars.Count - 2) - offset; } } if (close.ApproxCompare(renkoHigh) >= 0) { if (barOpen.ApproxCompare(renkoHigh - offset) != 0 || barHigh.ApproxCompare(Math.Max(renkoHigh - offset, renkoHigh)) != 0 || barLow.ApproxCompare(Math.Min(renkoHigh - offset, renkoHigh)) != 0) { RemoveLastBar(bars); AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, barTime, barVolume); } renkoLow = renkoHigh - 2.0 * offset; renkoHigh = renkoHigh + offset; isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } while (close.ApproxCompare(renkoHigh) >= 0) // Add empty bars to fill gap if price jumps { AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, renkoHigh), Math.Min(renkoHigh - offset, renkoHigh), renkoHigh, time, 0); renkoLow = renkoHigh - 2.0 * offset; renkoHigh = renkoHigh + offset; } // Add final partial bar AddBar(bars, renkoHigh - offset, Math.Max(renkoHigh - offset, close), Math.Min(renkoHigh - offset, close), close, time, volume); } else if (close.ApproxCompare(renkoLow) <= 0) { if (barOpen.ApproxCompare(renkoLow + offset) != 0 || barHigh.ApproxCompare(Math.Max(renkoLow + offset, renkoLow)) != 0 || barLow.ApproxCompare(Math.Min(renkoLow + offset, renkoLow)) != 0) { RemoveLastBar(bars); AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, barTime, barVolume); } renkoHigh = renkoLow + 2.0 * offset; renkoLow = renkoLow - offset; isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } while (close.ApproxCompare(renkoLow) <= 0) // Add empty bars to fill gap if price jumps { AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, renkoLow), Math.Min(renkoLow + offset, renkoLow), renkoLow, time, 0); renkoHigh = renkoLow + 2.0 * offset; renkoLow = renkoLow - offset; } // Add final partial bar AddBar(bars, renkoLow + offset, Math.Max(renkoLow + offset, close), Math.Min(renkoLow + offset, close), close, time, volume); } else { UpdateBar(bars, close, close, close, time, volume); } bars.LastPrice = close; }
//protected override void OnBarUpdate() //{ // //TODO: Write your owner OnBarUpdate handling // //DrawArrowUp("Arrowup" + CurrentBar, true, Bars.GetTime(Count - 1), Bars.GetLow(CurrentBar) - 300 * TickSize, Color.Red); // //DrawArrowDown("Arrowdown" + CurrentBar, true, Bars.GetTime(Count - 1), Bars.GetHigh(CurrentBar) + 300 * TickSize, Color.Green); // //Occurred.Set(-1); // //Entry.Set(Close[0]); //} protected override void OnBarUpdate() { //MyGap.Set(Input[0]); if (Bars != null && Bars.Count > 0) // && TimeFrame.Periodicity == DatafeedHistoryPeriodicity.Minute // && TimeFrame.PeriodicityValue == 15) { } else { return; } if (Bars.BarsSinceSession == 0) { sessionprocessed = false; } //08.00, 08.15, 08.30, 08.45, 09.00 sind abgeschlossen -> es ist 09.15) // if(Bars.BarsSinceSession == 5) if (ToTime(Bars.GetTime(CurrentBar)) > 90000 && //größer 09.00 geht für 15M und 1Std (und 1Tag?) sessionprocessed == false) //Tag noch nicht verarbeitet { sessionprocessed = true; GapTradeLong = GapTradeShort = false; IBar GapOpenBar = Bars.Where(x => x.Time.Date == Bars[0].Time.Date).FirstOrDefault(); //liefert erster kerze des tages double GapOpen = GapOpenBar.Open; double LastDayClose = PriorDayOHLC().PriorClose[0]; double GapSize = GapOpen - LastDayClose; DateTime LastDayCloseDate = Bars.GetTime(Count - 7); DateTime LastPeriod = Time[1]; if (LastDayClose != null && Math.Abs(LastDayClose - GapOpen) > _PunkteGapMin && Math.Abs(LastDayClose - GapOpen) < _PunkteGapMax) { //Wenn Gap größer 50 und kleiner 100 existgap = true; //Gap markieren (08.00 - 09.15) string strMyRect = "MyRect" + Count; string strMyGapSize = "MyGapSize" + Count; if (LastDayClose - GapOpen < 0) //Long { //Long //DrawRectangle(strMyRect, true, LastDayCloseDate, LastDayClose, LastPeriod, HighestHighPrice(5)[0], _col_gap, _col_gap, 70); DrawText(strMyGapSize, true, Math.Round(GapSize, 1).ToString(), LastDayCloseDate, LastDayClose + 25, 9, Color.Black, new Font("Areal", 9), StringAlignment.Center, Color.Black, Color.Azure, 1); // if (LinReg(5)[0] > GapOpen) if (LinReg(Closes[0], 5)[0] > GapOpen) { //Chancenreicher SuccessTrade string strArrowUp = "ArrowUp" + Bars.GetTime(CurrentBar); DrawArrowUp(strArrowUp, true, Bars.GetTime(Count - 1), Bars.GetOpen(CurrentBar) - 300 * TickSize, Color.Green); GapTradeLong = true; Occurred.Set(1); Entry.Set(Bars.GetOpen(CurrentBar)); } } else { //Short //DrawRectangle(strMyRect, true, LastDayCloseDate, LastDayClose, LastPeriod, LowestLowPrice(5)[0], Color.Pink, Color.Pink, 70); DrawText(strMyGapSize, true, Math.Round(GapSize, 1).ToString(), LastDayCloseDate, LastDayClose - 25, 9, Color.Black, new Font("Areal", 9), StringAlignment.Center, Color.Black, Color.Azure, 1); if (LinReg(Closes[0], 5)[0] < GapOpen) { ////Chancenreicher SuccessTrade string strArrowDown = "ArrowDown" + Bars.GetTime(CurrentBar); DrawArrowDown(strArrowDown, true, Bars.GetTime(Count - 1), Bars.GetOpen(CurrentBar) + 300 * TickSize, Color.Red); GapTradeShort = true; Occurred.Set(-1); Entry.Set(Bars.GetOpen(CurrentBar)); } } if (GapTradeShort == true || GapTradeLong == true) { Print("------------------" + Time[5] + "------------------"); Print("LineReg: " + Math.Round(LinReg(5)[0]), 1); Print("Gap Open: " + GapOpen); } } else { existgap = false; } } //09.15. - 09.30 Kerze else if (Bars.BarsSinceSession == 6 && existgap == true) { //Auswertung decimal GapTradeResult; Color colorTextBox; GapTradeResult = (decimal)Bars.GetClose(CurrentBar - 1) - (decimal)Bars.GetOpen(CurrentBar - 1); if (GapTradeLong == true) { //Long GapTradeCounterLong += 1; GapTradeResultTotalLong = GapTradeResultTotalLong + GapTradeResult; string strGapeTradeLong = "GapTradeLong" + CurrentBar; string strTradeResultLong; if (GapTradeResult < 0) { Print("FAAAAAAAAAAAAAAAIIIIIIIIIIIIIILLLLLLLLLL"); GapTradeFailCounterLong += 1; strTradeResultLong = "Fail " + GapTradeResult.ToString(); colorTextBox = colFail; } else { GapTradeWinCounterLong += 1; strTradeResultLong = "Win " + GapTradeResult.ToString(); colorTextBox = colWin; } DrawText(strGapeTradeLong, true, strTradeResultLong, Time[1], Bars.GetHigh(CurrentBar - 1) + 10, 9, Color.Black, new Font("Areal", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } else if (GapTradeShort == true) { //Short GapTradeCounterShort += 1; GapTradeResultTotalShort = GapTradeResultTotalShort - GapTradeResult; string strGapeTradeShort = "GapTradeLong" + CurrentBar; string strTradeResultShort; if (GapTradeResult > 0) { Print("FAAAAAAAAAAAAAAAIIIIIIIIIIIIIILLLLLLLLLL"); GapTradeFailCounterShort += 1; strTradeResultShort = "Fail " + GapTradeResult.ToString(); colorTextBox = colFail; } else { GapTradeWinCounterShort += 1; strTradeResultShort = "Win " + GapTradeResult.ToString(); colorTextBox = colWin; } DrawText(strGapeTradeShort, true, strTradeResultShort, Time[1], Bars.GetLow(CurrentBar - 1) - 10, 9, Color.Black, new Font("Areal", 9), StringAlignment.Center, Color.Black, colorTextBox, 70); } Print("Gap Trade Result: " + GapTradeResult); } if (Count == Bars.Count - 1) { Print("Total Trades Long: " + GapTradeCounterLong); Print("Wins Long: " + GapTradeWinCounterLong); Print("Fails Long: " + GapTradeFailCounterLong); Print("Total Trades Short: " + GapTradeCounterShort); Print("Wins Short: " + GapTradeWinCounterShort); Print("Fails Short: " + GapTradeFailCounterShort); if (GapTradeCounterLong > 0) { Print("Avg Long: " + (GapTradeResultTotalLong / GapTradeCounterLong)); } if (GapTradeCounterShort > 0) { Print("Avg Short: " + (GapTradeResultTotalShort / GapTradeCounterShort)); } } }
public override void Plot(Graphics graphics, Rectangle bounds, double min, double max) { if ((Bars == null) || (chartedMax < 0)) { return; } backBrush.Color = ChartControl.BackColor; int lastBar = Math.Min(LastBarIndexPainted, Bars.Count - 1); int firstBar = FirstBarIndexPainted; var th = ChartControl.GetYByValue(this, chartedMax) - ChartControl.GetYByValue(this, chartedMax + TickSize); float halfHeight = th / 2f; // a few heights and widths to set... bigrect.Height = th; totalsrect.Width = ChartControl.BarSpace; bigrect.Width = Math.Max(totalsrect.Width - (combinedvol?5:0), 1); lilrect.Height = th; lilrect.Width = bigrect.Width / 2.0f - 3; #region setupFonts if ((ChartControl.BarSpace != barWidth) || (th != tickHeight)) { // need to recompute the right fonts, then... //Print("New TickHeight! " + th + " vs. "+tickHeight); // DEBUG barWidth = ChartControl.BarSpace; tickHeight = th; if (deltaFont != null) { deltaFont.Dispose(); } if (totalsFont != null) { totalsFont.Dispose(); } deltaFont = null; totalsFont = null; float totwidth = Math.Min(Math.Max(totalsrect.Width / 4, 2), 18); totalsFont = new Font(FontFamily.GenericMonospace, totwidth, GraphicsUnit.Pixel); float delwidth = Math.Max(bigrect.Width / 6, 2); deltaFont = new Font(FontFamily.GenericMonospace, delwidth, GraphicsUnit.Pixel); if (deltaFont.Height > th) { deltaFont.Dispose(); deltaFont = new Font(FontFamily.GenericMonospace, Math.Max(bigrect.Height, 2), GraphicsUnit.Pixel); } } totalsrect.Height = totalsFont.Height; #endregion setupFonts // set up the dividing line for the summary information #region setupdivider double linprice = chartedMin; float linlvl = ChartControl.GetYByValue(this, linprice - 0.5 * TickSize); if (displaytotals) { // put the linlvl at the bottom, if that's lower than just below the // lowest chart price. var fromBottom = bounds.Bottom - totalsFont.Height * 4.5f; //Print("linlvl vs. frombottom: "+linlvl+" "+fromBottom); if (fromBottom > linlvl) { linlvl = fromBottom; linprice = Bars.Instrument.MasterInstrument.Round2TickSize(min + TickSize * (-1 + (totalsFont.Height * 4.5f) / tickHeight)); while (ChartControl.GetYByValue(this, linprice) < linlvl) { linprice -= TickSize; } while (ChartControl.GetYByValue(this, linprice) > linlvl) { linprice += TickSize; } linprice = Bars.Instrument.MasterInstrument.Round2TickSize(linprice); } } else { linprice = -1; linlvl = ChartControl.GetYByValue(this, min) + 999; } //Print("Final: "+linlvl); #endregion setupdivider // if we are using the graphical display, find the largest volume #region findlargestvol long mvol = 1; if (displaycandles && displaygraphical) { for (int indx = firstBar; indx <= lastBar; ++indx) { if ((indx <= CurrentBar) && (indx >= 1)) { var ed = extdat.getExtraData(CurrentBar - indx, this.Bars, CurrentBar); if (ed != null) { mvol = Math.Max(mvol, ed.findLargestLevel(combinedvol)); } } } } #endregion findlargestvol if (displaytotals || displaycandles) { for (int indx = firstBar; indx <= lastBar; ++indx) { if ((indx <= CurrentBar) && (indx >= 1)) { var ed = extdat.getExtraData(CurrentBar - indx, this.Bars, CurrentBar); if (ed != null) { // set up for the bar's location #region barXYlocation int x = ChartControl.GetXByBarIdx(BarsArray[0], indx); totalsrect.X = x - 0.5f * barWidth; bigrect.X = totalsrect.X + (combinedvol?5:0); #endregion barXYlocation // draw on the candle #region drawcandle if (displaycandles) { double miny = Bars.GetLow(indx); double maxy = Bars.GetHigh(indx); var candleY = ChartControl.GetYByValue(this, maxy); var candleH = ChartControl.GetYByValue(this, miny) - candleY; graphics.FillRectangle(backBrush, bigrect.X, candleY - bigrect.Height, bigrect.Width, candleH + 2 * bigrect.Height); var openCoord = ChartControl.GetYByValue(this, Bars.GetOpen(indx)); var closeCoord = ChartControl.GetYByValue(this, Bars.GetClose(indx)); paintBrush.Color = ChartControl.ChartStyle.Pen2.Color; // candle wick color... var stemX = (combinedvol?(bigrect.X - 4):(bigrect.X + lilrect.Width + 2)); graphics.FillRectangle(paintBrush, stemX, candleY, 2, candleH); if (openCoord == closeCoord) { graphics.FillRectangle(paintBrush, stemX - 1, openCoord - 1, 4, 2); } else if (openCoord > closeCoord) { paintBrush.Color = ChartControl.UpColor; graphics.FillRectangle(paintBrush, stemX - 1, closeCoord, 4, openCoord - closeCoord); } else { paintBrush.Color = ChartControl.DownColor; graphics.FillRectangle(paintBrush, stemX - 1, openCoord, 4, closeCoord - openCoord); } // now paint the bar prices... #region barpainting long put, pdt; // price upticks, price downticks var ynext = ChartControl.GetYByValue(this, maxy) - halfHeight; var lowboundary = (miny - TickSize / 2); for (double cury = maxy; cury > lowboundary; cury -= TickSize) { ed.getUpDnTicksAtPrice(TickSize, cury, out put, out pdt); bigrect.Y = ynext; ynext = ChartControl.GetYByValue(this, cury - TickSize) - halfHeight; bigrect.Height = ynext - bigrect.Y; lilrect.Y = bigrect.Y; lilrect.Height = bigrect.Height; if (combinedvol) { var cvol = put + pdt; if (cvol < 1) { cvol = 1; } var ratio = ((float)put) / ((float)cvol); if (ratio >= 0.75) { paintBrush.Color = upcolor; } else if (ratio <= 0.25) { paintBrush.Color = dncolor; } else { paintBrush.Color = neutcolor; } if (displaygraphical) { var w = ((float)cvol) * bigrect.Width / ((float)mvol); graphics.FillRectangle(paintBrush, bigrect.X, bigrect.Y, w, bigrect.Height); } else { graphics.DrawString(cvol.ToString(), deltaFont, paintBrush, bigrect, leftFormat); } } else { paintBrush.Color = dncolor; lilrect.X = bigrect.X; if (displaygraphical) { var w = ((float)pdt) * lilrect.Width / ((float)mvol); graphics.FillRectangle(paintBrush, lilrect.X + lilrect.Width - w, lilrect.Y, w, lilrect.Height); } else { graphics.DrawString(pdt.ToString(), deltaFont, paintBrush, lilrect, rightFormat); } paintBrush.Color = upcolor; lilrect.X += lilrect.Width + 6; if (displaygraphical) { var w = ((float)put) * lilrect.Width / ((float)mvol); graphics.FillRectangle(paintBrush, lilrect.X, lilrect.Y, w, lilrect.Height); } else { graphics.DrawString(put.ToString(), deltaFont, paintBrush, lilrect, leftFormat); } } } #endregion barpainting } #endregion drawcandle // draw totals at the bottom #region drawtotals if (displaytotals) { double denom = Math.Max(1, ed.UpTicks + ed.DnTicks); paintBrush.Color = upcolor; totalsrect.Y = linlvl; int pctage = (int)(Math.Round((double)ed.UpTicks * 100.0 / denom)); graphics.DrawString(String.Format("{0}%", pctage), totalsFont, paintBrush, totalsrect, centerFormat); totalsrect.Y = totalsrect.Y + totalsFont.Height; graphics.DrawString(ed.UpTicks.ToString(), totalsFont, paintBrush, totalsrect, centerFormat); paintBrush.Color = dncolor; totalsrect.Y = totalsrect.Y + totalsFont.Height; graphics.DrawString(ed.DnTicks.ToString(), totalsFont, paintBrush, totalsrect, centerFormat); totalsrect.Y = totalsrect.Y + totalsFont.Height; graphics.DrawString(String.Format("{0}%", 100 - pctage), totalsFont, paintBrush, totalsrect, centerFormat); } #endregion drawtotals } } } } // draw the dividing line #region drawdivider if (displaytotals) { linpen.Color = neutcolor; graphics.DrawLine(linpen, bounds.Left, linlvl, bounds.Right, linlvl); //Print("totalsFont height *4 = "+(4*totalsFont.Height)); } #endregion drawdivider // now display the volume profile, if needed... #region dispvolprofile if (displayvolprofile) { var edcbar = extdat.getExtraData(0, Bars, CurrentBar); if (edcbar != null) { var dispmax = Bars.Instrument.MasterInstrument.Round2TickSize(max); var dispmin = Bars.Instrument.MasterInstrument.Round2TickSize(Math.Max(linprice, min)); var idxhigh = vprofIndex(dispmax); var idxlow = vprofIndex(dispmin); long maxvprof = 1; // figure out where the current bar fits in... int idxcbarh = idxhigh + (int)Math.Round((dispmax - Bars.GetHigh(CurrentBar)) / TickSize); int idxcbarl = idxhigh + (int)Math.Round((dispmax - Bars.GetLow(CurrentBar)) / TickSize); long stored, recentup, recentdn; for (int i = idxhigh; i <= idxlow; ++i) { stored = vprofile[i]; if ((!useprevsession) && (i >= idxcbarh) && (i <= idxcbarl)) { edcbar.getUpDnTicksAtPrice(TickSize, dispmax - ((i - idxhigh) * TickSize), out recentup, out recentdn); stored += (recentup + recentdn); } if (stored > maxvprof) { maxvprof = stored; } } paintBrush.Color = sessionProfileColor; var profY2 = ChartControl.GetYByValue(this, dispmax) - halfHeight; for (int i = idxhigh; i <= idxlow; ++i) { var profY = profY2; profY2 = ChartControl.GetYByValue(this, dispmax - (i - idxhigh + 1) * TickSize) - halfHeight; if (profY2 > linlvl) { profY2 = linlvl; } if (profY == profY2) { continue; } stored = vprofile[i]; if ((!useprevsession) && (i >= idxcbarh) && (i <= idxcbarl)) { edcbar.getUpDnTicksAtPrice(TickSize, dispmax - ((i - idxhigh) * TickSize), out recentup, out recentdn); stored += (recentup + recentdn); } if (stored > 0) { graphics.FillRectangle(paintBrush, bounds.Left, profY, stored * (bounds.Width / 2) / maxvprof, profY2 - profY); } } } } #endregion dispvolprofile // now paint the tradedamounts, if needed.... #region tradedamts if (displaytradedamounts && (lastBar == CurrentBar)) { paintBrush.Color = neutcolor; lilrect.X = ChartControl.GetXByBarIdx(BarsArray[0], lastBar) + barWidth; if (tradedPrices[0] > 0) { lilrect.Y = ChartControl.GetYByValue(this, tradedPrices[0]) - halfHeight; graphics.DrawString(tradedAmounts[0].ToString(), deltaFont, paintBrush, lilrect, rightFormat); } if (tradedPrices[1] > 0) { lilrect.Y = ChartControl.GetYByValue(this, tradedPrices[1]) - halfHeight; graphics.DrawString(tradedAmounts[1].ToString(), deltaFont, paintBrush, lilrect, rightFormat); } } #endregion tradedamts }