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); } bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } if (bars.BarsPeriod.Value == 1) { AddBar(bars, open, high, low, close, time, volume, bid, ask); } else if (bars.Count == 0) { AddBar(bars, open, high, low, close, time, volume); } else if (bars.Count > 0 && (!bars.IsResetOnNewTradingDay || !isNewSession) && bars.BarsPeriod.Value > 1 && bars.TickCount < bars.BarsPeriod.Value) { UpdateBar(bars, high, low, close, time, volume); } else { AddBar(bars, open, high, low, close, time, volume); } }
protected override void OnBarUpdate() { // Reset for every session if (sessionIterator.IsNewSession(Time[0], false)) { sessionIterator.GetNextSession(Time[0], false); } // Sometimes CurrentDayOHL is not initialized yet for new session. IDKW if (CurrentDayOHL().CurrentHigh[0] == 0 || CurrentDayOHL().CurrentLow[0] == 0) { return; } MidPoint[0] = ((CurrentDayOHL().CurrentHigh[0] - CurrentDayOHL().CurrentLow[0]) / 2) + CurrentDayOHL().CurrentLow[0]; // Set brush to Transparent on first tick of new session // to disconnect indicator plot between sesions. Plots are // relative to current bar and last bar. if (Bars.IsFirstBarOfSession && IsFirstTickOfBar) { PlotBrushes[0][0] = Brushes.Transparent; } // Draw line between start of session and first bar since the // plot is set to transparent for the session disconnect effect if (Bars.IsFirstBarOfSession) { RemoveDrawObject(Time[0].Date.ToString() + "mid"); Draw.Line(this, Time[0].Date.ToString() + "mid", true, sessionIterator.ActualSessionBegin, MidPoint[0], Time[0], MidPoint[0], Plots[0].Brush, Plots[0].DashStyleHelper, (int)Plots[0].Pen.Thickness); } }
private DateTime TimeToBarTime(Bars bars, DateTime time, bool isBar) { if (SessionIterator.IsNewSession(time, isBar)) { SessionIterator.GetNextSession(time, isBar); } if (bars.IsResetOnNewTradingDay || !bars.IsResetOnNewTradingDay && bars.Count == 0) { DateTime barTimeStamp = isBar ? SessionIterator.ActualSessionBegin.AddSeconds(Math.Ceiling(Math.Ceiling(Math.Max(0, time.Subtract(SessionIterator.ActualSessionBegin).TotalSeconds)) / bars.BarsPeriod.Value) * bars.BarsPeriod.Value) : SessionIterator.ActualSessionBegin.AddSeconds(bars.BarsPeriod.Value + Math.Floor(Math.Floor(Math.Max(0, time.Subtract(SessionIterator.ActualSessionBegin).TotalSeconds)) / bars.BarsPeriod.Value) * bars.BarsPeriod.Value); if (bars.TradingHours.Sessions.Count > 0 && barTimeStamp > SessionIterator.ActualSessionEnd) // Cut last bar in session down to session end on odd session end time { barTimeStamp = SessionIterator.ActualSessionEnd; } return(barTimeStamp); } else { DateTime lastBarTime = bars.GetTime(bars.Count - 1); DateTime barTimeStamp = isBar ? lastBarTime.AddSeconds(Math.Ceiling(Math.Ceiling(Math.Max(0, time.Subtract(lastBarTime).TotalSeconds)) / bars.BarsPeriod.Value) * bars.BarsPeriod.Value) : lastBarTime.AddSeconds(bars.BarsPeriod.Value + Math.Floor(Math.Floor(Math.Max(0, time.Subtract(lastBarTime).TotalSeconds)) / bars.BarsPeriod.Value) * bars.BarsPeriod.Value); if (bars.TradingHours.Sessions.Count > 0 && barTimeStamp > SessionIterator.ActualSessionEnd) { DateTime saveActualSessionEnd = SessionIterator.ActualSessionEnd; SessionIterator.GetNextSession(SessionIterator.ActualSessionEnd.AddSeconds(1), isBar); barTimeStamp = SessionIterator.ActualSessionBegin.AddSeconds((int)barTimeStamp.Subtract(saveActualSessionEnd).TotalSeconds); } return(barTimeStamp); } }
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); } bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } long barsPeriodValue = bars.BarsPeriod.Value; if (bars.Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency) { barsPeriodValue = Core.Globals.FromCryptocurrencyVolume(bars.BarsPeriod.Value); } if (bars.Count == 0) { while (volume > barsPeriodValue) { AddBar(bars, open, high, low, close, time, barsPeriodValue); volume -= barsPeriodValue; } if (volume > 0) { AddBar(bars, open, high, low, close, time, volume); } } else { long volumeTmp = 0; if (!bars.IsResetOnNewTradingDay || !isNewSession) { volumeTmp = Math.Min(barsPeriodValue - bars.GetVolume(bars.Count - 1), volume); if (volumeTmp > 0) { UpdateBar(bars, high, low, close, time, volumeTmp); } } volumeTmp = volume - volumeTmp; while (volumeTmp > 0) { AddBar(bars, open, high, low, close, time, Math.Min(volumeTmp, barsPeriodValue)); volumeTmp -= barsPeriodValue; } } }
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) { 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 (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.Value || isBar && bars.Count > 0 && barTime == bars.LastBarTime.Date || !isBar && bars.Count > 0 && barTime <= bars.LastBarTime.Date) { UpdateBar(bars, high, low, close, barTime, volume); } else { AddBar(bars, open, high, low, close, barTime, volume); } } }
protected override void OnMarketData(MarketDataEventArgs marketDataUpdate) { // Workaround for market replay backfilling all of replay sessions data(as historical data) // Replay should only backfill history up to replay time, so make sure any historical ticks // are before the current replay time. if ((Connection.PlaybackConnection != null) && (State == State.Historical) && (marketDataUpdate.Time >= Connection.PlaybackConnection.Now)) { if (PrintDebug) { Print("Filter Hit - MarketDataEvent Time :" + marketDataUpdate.Time.ToString() + " Playback Time: " + Connection.PlaybackConnection.Now.ToString() + " Event Type: " + marketDataUpdate.MarketDataType + " State: " + State); } return; } // Reset for every session if (sessionIterator.IsNewSession(marketDataUpdate.Time, false)) { if (PrintDebug) { Print("NewSession: " + marketDataUpdate.Time.ToString()); } totalShares = 0; totalDollars = 0; sessionIterator.GetNextSession(marketDataUpdate.Time, false); } // Check session time if (!sessionIterator.IsInSession(marketDataUpdate.Time, false, true)) { return; } // Is this a trade(not bid or ask) if (marketDataUpdate.MarketDataType == MarketDataType.Last) { totalShares += marketDataUpdate.Volume; totalDollars += marketDataUpdate.Volume * marketDataUpdate.Price; Vwap[0] = totalDollars / totalShares; if (PrintDebug) { Print(marketDataUpdate.Time.ToString() + " Session total shares: " + totalShares.ToString() + " " + State); } } }
private DateTime TimeToBarTimeSecond(Bars bars, DateTime time, bool isBar) { if (SessionIterator.IsNewSession(time, isBar)) { SessionIterator.GetNextSession(time, isBar); } DateTime barTimeStamp = SessionIterator.ActualSessionBegin.AddSeconds(Math.Ceiling(Math.Ceiling(Math.Max(0, time.Subtract(SessionIterator.ActualSessionBegin).TotalSeconds)) / bars.BarsPeriod.BaseBarsPeriodValue) * bars.BarsPeriod.BaseBarsPeriodValue); if (bars.TradingHours.Sessions.Count > 0 && barTimeStamp > SessionIterator.ActualSessionEnd) { barTimeStamp = SessionIterator.ActualSessionEnd <= Core.Globals.MinDate ? barTimeStamp : SessionIterator.ActualSessionEnd; } return(barTimeStamp); }
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); } bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } #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 = anchorPrice = bars.GetClose(bars.Count - 1); } } switch (BarsPeriod.BaseBarsPeriodType) { case BarsPeriodType.Day: tmpTime = time.Date; if (!isBar) { tmpDayCount++; if (tmpTime < time.Date) { tmpTime = time.Date; // Make sure timestamps are ascending } } if (isBar && prevTimeD != tmpTime) { tmpDayCount++; } if (isBar && bars.Count > 0 && tmpTime == bars.LastBarTime.Date || !isBar && bars.Count > 0 && tmpTime <= bars.LastBarTime.Date || tmpDayCount < BarsPeriod.BaseBarsPeriodValue) { endOfBar = false; } else { prevTime = prevTimeD == Core.Globals.MinDate ? tmpTime : prevTimeD; prevTimeD = 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 >= BarsPeriod.BaseBarsPeriodValue; prevTime = tmpTime = time; if (endOfBar) { tmpVolume = 0; } break; } tmpVolume += volume; endOfBar = tmpVolume >= BarsPeriod.BaseBarsPeriodValue; if (endOfBar) { prevTime = tmpTime; tmpVolume = 0; tmpTime = time; } break; case BarsPeriodType.Month: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeMonth(time, 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, BarsPeriod.BaseBarsPeriodValue); } break; case BarsPeriodType.Second: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeSecond(bars, time, isBar); } if (time <= tmpTime) { endOfBar = false; } else { prevTime = tmpTime; tmpTime = TimeToBarTimeSecond(bars, time, isBar); endOfBar = true; } break; case BarsPeriodType.Tick: if (tmpTime == Core.Globals.MinDate || BarsPeriod.BaseBarsPeriodValue == 1) { prevTime = tmpTime; if (prevTime == Core.Globals.MinDate) { prevTime = time; } tmpTime = time; endOfBar = BarsPeriod.BaseBarsPeriodValue == 1; break; } if (tmpTickCount < BarsPeriod.BaseBarsPeriodValue) { tmpTime = time; endOfBar = false; tmpTickCount++; } else { prevTime = tmpTime; tmpTime = time; endOfBar = true; tmpTickCount = 1; } break; case BarsPeriodType.Week: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, BarsPeriod.BaseBarsPeriodValue); } if (time.Date <= tmpTime.Date) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeWeek(time.Date, tmpTime.Date, BarsPeriod.BaseBarsPeriodValue); } break; case BarsPeriodType.Year: if (tmpTime == Core.Globals.MinDate) { prevTime = tmpTime = TimeToBarTimeYear(time, BarsPeriod.BaseBarsPeriodValue); } if (time.Year <= tmpTime.Year) { endOfBar = false; } else { prevTime = tmpTime; endOfBar = true; tmpTime = TimeToBarTimeYear(time, BarsPeriod.BaseBarsPeriodValue); } break; } #endregion #region P&F logic double tickSize = bars.Instrument.MasterInstrument.TickSize; boxSize = Math.Floor(10000000.0 * BarsPeriod.Value * tickSize) / 10000000.0; reversalSize = BarsPeriod.Value2 * boxSize; if (bars.Count == 0 || IsIntraday && bars.IsResetOnNewTradingDay && isNewSession) { if (bars.Count > 0) { 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, lastHigh, lastLow, lastClose, prevTime == Core.Globals.MinDate ? time : prevTime, lastTime); } } AddBar(bars, close, close, close, close, tmpTime, volume); anchorPrice = close; trend = Trend.Undetermined; prevTime = tmpTime; volumeCount = 0; bars.LastPrice = close; tmpCount = bars.Count; tmpHigh = high; tmpLow = low; return; } double c = bars.GetClose(bars.Count - 1); double h = bars.GetHigh(bars.Count - 1); double l = bars.GetLow(bars.Count - 1); DateTime t = bars.GetTime(bars.Count - 1); if (endOfBar) { CalculatePfBar(bars, h, l, c, prevTime, t); 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; }
protected override void OnDataPoint(Bars bars, double open, double high, double low, double close, DateTime time, long volume, bool isBar, double bid, double ask) { ///Beta 9 addition! // build a session iterator from the bars object being updated if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } // check if we are in a new trading session based on the trading hours selected by the user bool isNewSession = SessionIterator.IsNewSession(time, isBar); // calculate the new trading day if (isNewSession) { SessionIterator.CalculateTradingDay(time, isBar); } ///End Beta 9 addition //### First Bar if (bars.Count == 0 || (bars.IsResetOnNewTradingDay && isNewSession)) { tickSize = bars.Instrument.MasterInstrument.TickSize; trendOffset = bars.BarsPeriod.Value * tickSize; reversalOffset = bars.BarsPeriod.Value2 * tickSize; //bars.BarPeriod.BaseBarsPeriodValue = bars.BarsPeriod.Value; //### Remove to customize OpenOffset openOffset = Math.Ceiling((double)bars.BarsPeriod.BaseBarsPeriodValue * 1) * tickSize; barOpen = close; barMax = barOpen + (trendOffset * barDirection); barMin = barOpen - (trendOffset * barDirection); AddBar(bars, barOpen, barOpen, barOpen, barOpen, time, volume); } //### Subsequent Bars else { 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; barDirection = maxExceeded ? 1 : minExceeded ? -1 : 0; fakeOpen = thisClose - (openOffset * barDirection); //### Fake Open is halfway down the bar //### Close Current Bar UpdateBar(bars, (maxExceeded ? thisClose : bars.GetHigh(bars.Count - 1)), (minExceeded ? thisClose : bars.GetLow(bars.Count - 1)), thisClose, time, volume); //### 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); } //### Current Bar Still Developing else { UpdateBar(bars, (close > bars.GetHigh(bars.Count - 1) ? close : bars.GetHigh(bars.Count - 1)), (close < bars.GetLow(bars.Count - 1) ? close : bars.GetLow(bars.Count - 1)), 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) { if (SessionIterator == null) { SessionIterator = new SessionIterator(bars); } bool isNewSession = SessionIterator.IsNewSession(time, isBar); if (isNewSession) { SessionIterator.GetNextSession(time, isBar); } if (bars.Count == 0 || bars.IsResetOnNewTradingDay && isNewSession) { AddBar(bars, open, high, low, close, time, volume); } else { double barClose = bars.GetClose(bars.Count - 1); double barHigh = bars.GetHigh(bars.Count - 1); double barLow = bars.GetLow(bars.Count - 1); double tickSize = bars.Instrument.MasterInstrument.TickSize; double rangeValue = Math.Floor(10000000.0 * bars.BarsPeriod.Value * tickSize) / 10000000.0; if (close.ApproxCompare(barLow + rangeValue) > 0) { double newClose = barLow + rangeValue; // Every bar closes either with high or low if (newClose.ApproxCompare(barClose) > 0) { UpdateBar(bars, newClose, barLow, newClose, time, 0); } // If there's still a gap, fill with phantom bars double newBarOpen = newClose + tickSize; while (close.ApproxCompare(newClose) > 0) { newClose = Math.Min(close, newBarOpen + rangeValue); AddBar(bars, newBarOpen, newClose, newBarOpen, newClose, time, close.ApproxCompare(newClose) > 0 ? 0 : volume); newBarOpen = newClose + tickSize; } } else if ((barHigh - rangeValue).ApproxCompare(close) > 0) { double newClose = barHigh - rangeValue; // Every bar closes either with high or low if (barClose.ApproxCompare(newClose) > 0) { UpdateBar(bars, barHigh, newClose, newClose, time, 0); } // if there's still a gap, fill with phantom bars double newBarOpen = newClose - tickSize; while (newClose.ApproxCompare(close) > 0) { newClose = Math.Max(close, newBarOpen - rangeValue); AddBar(bars, newBarOpen, newBarOpen, newClose, newClose, time, newClose.ApproxCompare(close) > 0 ? 0 : volume); newBarOpen = newClose - tickSize; } } 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) { // 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; }
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 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; }
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 }
protected override void OnMarketData(MarketDataEventArgs marketDataUpdate) { // Workaround for market replay sending out all of replay sessions data(as historical data) // Replay should only backfill history up to replay time, so make sure any historical ticks // are before the current replay time. // this code to OnBar and set for on price change notifications for better performance once // this bug is resolved if ((Connection.PlaybackConnection != null) && (State == State.Historical) && (marketDataUpdate.Time >= Connection.PlaybackConnection.Now)) { return; } bool redrawHigh = false; bool redrawLow = false; // Reset for every session if (sessionIterator.IsNewSession(marketDataUpdate.Time, true)) { orHigh = Double.MinValue; orLow = Double.MaxValue; sessionIterator.GetNextSession(marketDataUpdate.Time, true); renderEndTime = sessionIterator.ActualSessionEnd; orCutoffTime = sessionIterator.ActualSessionBegin.AddSeconds(CutoffSeconds); rendered = false; orComplete = false; } if (orComplete) { return; } // Check session time if (!sessionIterator.IsInSession(marketDataUpdate.Time, false, true)) { return; } // keep track of high low if (marketDataUpdate.MarketDataType == MarketDataType.Last) { if (!orComplete && (marketDataUpdate.Time <= orCutoffTime)) { redrawHigh = false; if (marketDataUpdate.Price > orHigh) { orHigh = marketDataUpdate.Price; orHighDateTime = marketDataUpdate.Time; redrawHigh = true; Values[0][0] = orHigh; } redrawLow = false; if (marketDataUpdate.Price < orLow) { orLow = marketDataUpdate.Price; orLowDateTime = marketDataUpdate.Time; redrawLow = true; Values[1][0] = orLow; } if (redrawHigh) { RemoveDrawObject(marketDataUpdate.Time.Date.ToString() + "or_high"); Draw.Line(this, marketDataUpdate.Time.Date.ToString() + "or_high", true, orHighDateTime, orHigh, renderEndTime, orHigh, HighBrush, DashStyleHelper.Dot, HighBrushWidth); } if (redrawLow) { RemoveDrawObject(marketDataUpdate.Time.Date.ToString() + "or_low"); Draw.Line(this, marketDataUpdate.Time.Date.ToString() + "or_low", true, orLowDateTime, orLow, renderEndTime, orLow, LowBrush, DashStyleHelper.Dot, LowBrushWidth); } } // On first tick past cutoff time mark opening range calc complete and // draw the hi and low lines across the entire sesson. if ((marketDataUpdate.Time > orCutoffTime) && !orComplete) { orComplete = true; RemoveDrawObject(marketDataUpdate.Time.Date.ToString() + "or_high"); Draw.Line(this, marketDataUpdate.Time.Date.ToString() + "or_high", true, orHighDateTime, orHigh, renderEndTime, orHigh, HighBrush, DashStyleHelper.Solid, HighBrushWidth); RemoveDrawObject(marketDataUpdate.Time.Date.ToString() + "or_low"); Draw.Line(this, marketDataUpdate.Time.Date.ToString() + "or_low", true, orLowDateTime, orLow, renderEndTime, orLow, LowBrush, DashStyleHelper.Solid, LowBrushWidth); // Go back to first bar and Set all the high and low plot // values for the day so databox works for indicator for (int x = 0; x < Bars.BarsSinceNewTradingDay; x++) { Values[0][x] = orHigh; Values[1][x] = orLow; } } } }