/// <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 (volume <= bars.Period.Value2) return; if (bars.Count == 0) { while (volume > bars.Period.Value) { AddBar(bars, open, high, low, close, time, bars.Period.Value, isRealtime); volume -= bars.Period.Value; } if (volume > 0) AddBar(bars, open, high, low, close, time, volume, isRealtime); } else { long volumeTmp = 0; if (!bars.IsNewSession(time, isRealtime)) { volumeTmp = Math.Min(bars.Period.Value - bars.GetVolume(bars.Count - 1), volume); if (volumeTmp > 0) UpdateBar(bars, open, high, low, close, time, volumeTmp, isRealtime); } volumeTmp = volume - volumeTmp; while (volumeTmp > 0) { AddBar(bars, open, high, low, close, time, Math.Min(volumeTmp, bars.Period.Value), isRealtime); volumeTmp -= bars.Period.Value; } } }
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; } } }
/// <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 (volume <= bars.Period.Value2) { return; } if (bars.Count == 0) { while (volume > bars.Period.Value) { AddBar(bars, open, high, low, close, time, bars.Period.Value, isRealtime); volume -= bars.Period.Value; } if (volume > 0) { AddBar(bars, open, high, low, close, time, volume, isRealtime); } } else { long volumeTmp = 0; if (!bars.IsNewSession(time, isRealtime)) { volumeTmp = Math.Min(bars.Period.Value - bars.GetVolume(bars.Count - 1), volume); if (volumeTmp > 0) { UpdateBar(bars, open, high, low, close, time, volumeTmp, isRealtime); } } volumeTmp = volume - volumeTmp; while (volumeTmp > 0) { AddBar(bars, open, high, low, close, time, Math.Min(volumeTmp, bars.Period.Value), isRealtime); volumeTmp -= bars.Period.Value; } } }
public override double GetPercentComplete(Bars bars, DateTime now) { switch (BarsPeriod.BaseBarsPeriodType) { case BarsPeriodType.Day: return(now.Date <= bars.LastBarTime.Date ? 1.0 - bars.LastBarTime.AddDays(1).Subtract(now).TotalDays / bars.BarsPeriod.BaseBarsPeriodValue : 1); case BarsPeriodType.Minute: return(now <= bars.LastBarTime ? 1.0 - bars.LastBarTime.Subtract(now).TotalMinutes / bars.BarsPeriod.BaseBarsPeriodValue : 1); case BarsPeriodType.Month: if (now.Date <= bars.LastBarTime.Date) { int month = now.Month; int daysInMonth = month == 2 ? (DateTime.IsLeapYear(now.Year) ? 29 : 28) : (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12 ? 31 : 30); return((daysInMonth - bars.LastBarTime.Date.AddDays(1).Subtract(now).TotalDays / bars.BarsPeriod.BaseBarsPeriodValue) / daysInMonth); } return(1); case BarsPeriodType.Second: return(now <= bars.LastBarTime ? 1.0 - bars.LastBarTime.Subtract(now).TotalSeconds / bars.BarsPeriod.BaseBarsPeriodValue : 1); case BarsPeriodType.Tick: return((double)bars.TickCount / bars.BarsPeriod.BaseBarsPeriodValue); case BarsPeriodType.Volume: return(bars.Count == 0 ? 0 : (double)bars.GetVolume(bars.Count - 1) / bars.BarsPeriod.BaseBarsPeriodValue); case BarsPeriodType.Week: return(now.Date <= bars.LastBarTime.Date ? (7 - bars.LastBarTime.AddDays(1).Subtract(now).TotalDays / bars.BarsPeriod.BaseBarsPeriodValue) / 7 : 1); case BarsPeriodType.Year: if (now.Date <= bars.LastBarTime.Date) { double daysInYear = DateTime.IsLeapYear(now.Year) ? 366 : 365; return((daysInYear - bars.LastBarTime.Date.AddDays(1).Subtract(now).TotalDays / bars.BarsPeriod.BaseBarsPeriodValue) / daysInYear); } return(1); default: return(1); } }
// protected override void OnBarUpdate() { double currentBarSize = (float)Math.Abs(Open[0] - Close[0]); if (CurrentBar > 2) { // if (Int32.Parse(MyStopW.ElapsedTime) >= 5) { long volumeValue = Bars.GetVolume(CurrentBar); // if (volumeValue >= volumenTarget && currentBarSize >= candleSize) { // if (emailSent == false && CurrentBar != emailBar) { emailSent = true; emailBar = CurrentBar; string filePath = pathAssembler(CurrentBar.ToString()); SaveScreenShot(filePath); // string message = string.Format("- Alert!!! The volume of the current bar is above target, current bar volumen of {0} and bar size of {1}", volumeValue.ToString(), currentBarSize.ToString()); string subject = "Nestor Colt Informatic Trading Solutions"; // Send email : Thread.Sleep(1000); Sender.composeMessage("*****@*****.**", Email, subject, message, filePath); Print("Email Sent"); } } else if (volumeValue < 50 && CurrentBar != emailBar) { emailSent = false; } } } }
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 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; } }
/// <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) { 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); } 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; }
/// <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 OnBarUpdate() { // Get time of first bar on chart if (isFirstChartBar) { isFirstChartBar = false; chartStartTime = Time[0]; } // Not Enough History to calc rel vol if (Time[0].Date.AddDays(LookBackDays * -1) < chartStartTime.Date) { return; } // Only gather vol history on first tick // of bar since history does not change for // a given bar if (IsFirstTickOfBar) { int skipDays = 0; totalHistPeriodVol = 0; histPeriodVol = new List <double>(LookBackDays); // Loop until all same timeperiod lookback days // are found or lookback exceeds history while (histPeriodVol.Count < LookBackDays) { // Bar target time DateTime tt = Time[0].AddDays((histPeriodVol.Count + 1 + skipDays) * -1); // Bail if target day is before first chart, not enough history if (tt.Date < Time[CurrentBar].Date) { return; } // No weekends if ((tt.DayOfWeek == DayOfWeek.Saturday) || (tt.DayOfWeek == DayOfWeek.Sunday)) { skipDays++; continue; } // Skip over early close days and Holidays if (TradingHours.PartialHolidays.ContainsKey(tt.Date) || TradingHours.Holidays.ContainsKey(tt.Date)) { skipDays++; continue; } // Get Prev day's same time bar int relPrevBar = ChartBars.GetBarIdxByTime(ChartControl, tt); // If the returned bar is not the expected date, a bar with the // timetarget is not on the chart. Dont know why GetBarIdxByTime // does not return something more normal(like a -1) for a GetBarIdxXXX() // miss. Instead it just returns the incorrect bar. // At this point a missing bar is unexpected if (tt != Bars.GetTime(relPrevBar)) { throw new Exception("Missing data error - Target Time: " + tt + " Found Time: " + Bars.GetTime(relPrevBar)); } totalHistPeriodVol += Bars.GetVolume(relPrevBar); histPeriodVol.Add(Bars.GetVolume(relPrevBar)); } histPeriodVolStd = this.getStandardDeviation(histPeriodVol); avgHistPeriodVol = totalHistPeriodVol / LookBackDays; } // Get historical average at time volume from last x days Values[3][0] = avgHistPeriodVol; // Difference between avg period vol and current bars vol double rel_vol_diff = Volume[0] - avgHistPeriodVol; // Std Hi-Low Hash marks Values[1][0] = Math.Max(0.0, avgHistPeriodVol - histPeriodVolStd); Values[2][0] = avgHistPeriodVol + histPeriodVolStd; // Raw period volume bars, color code based on // volume above, below or within 1 std band Values[0][0] = Volume[0]; if (ShowVolumeBars) { // Greater than one std if (Volume[0] > Values[2][0]) { PlotBrushes[0][0] = VolAboveStdBrush; } // Within one std else if (Values[0][0] > Values[1][0]) { PlotBrushes[0][0] = VolWithinStdBrush; } // Less than 1 std else { PlotBrushes[0][0] = VolBelowStdBrush; } } else { PlotBrushes[0][0] = Brushes.Transparent; } }
public override void OnRender(ChartControl chartControl, ChartScale chartScale, ChartBars chartBars) { Bars bars = chartBars.Bars; Vector2 point0 = new Vector2(); Vector2 point1 = new Vector2(); RectangleF rect = new RectangleF(); float maxHalfWidth = (GetBarPaintWidth(BarWidthUI) - 1) / 2; float maxMeanAvgVol = 0; for (int idx = chartBars.FromIndex; idx < chartBars.ToIndex; idx++) { float meanAvg = (bars.GetVolume(idx) + bars.GetVolume(idx + 1)) / 2; if (meanAvg > maxMeanAvgVol) { maxMeanAvgVol = meanAvg; } } 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)); float barWidth = 1 + (2 * (float)Math.Round(bars.GetVolume(idx) / maxMeanAvgVol * maxHalfWidth)); 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 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; }
/// <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; }
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 }
public override double GetPercentComplete(Bars bars, DateTime now) { return(bars.Count == 0 ? 0 : (double)bars.GetVolume(bars.Count - 1) / bars.BarsPeriod.Value); }
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; }
/// <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: if (bars.Count == 0) { if (isRealtime && bars.Session.SessionsOfDay.Length > 0) { DateTime barTime; bars.Session.GetSessionDate(time, false, out barTime, out cacheSessionEnd); AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, barTime, volume, true); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time.Date, volume, isRealtime); } } else { DateTime barTime; if (!isRealtime) { barTime = time.Date; } else if (time >= cacheSessionEnd /* on realtime include60 is always false */) { bars.Session.GetSessionDate(time, false, out barTime, out cacheSessionEnd); if (barTime < bars.TimeLastBar.Date) { barTime = bars.TimeLastBar.Date; // make sure timestamps are ascending } } else { barTime = bars.TimeLastBar.Date; // make sure timestamps are ascending } if (bars.DayCount < bars.Period.Value || (!isRealtime && bars.Count > 0 && barTime == bars.TimeLastBar.Date) || (isRealtime && bars.Count > 0 && barTime <= bars.TimeLastBar.Date)) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, barTime, volume, isRealtime); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, barTime, volume, isRealtime); } } break; case PeriodType.Minute: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.Value, isRealtime), volume, isRealtime); } else { if (isRealtime && time < bars.TimeLastBar) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, true); } else if (!isRealtime && time <= bars.TimeLastBar) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, false); } else { time = TimeToBarTimeMinute(bars, time, bars.Session.NextBeginTime, bars.Period.Value, isRealtime); AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } } break; case PeriodType.Volume: if (bars.Count == 0) { while (volume > bars.Period.Value) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, bars.Period.Value, isRealtime); volume -= bars.Period.Value; } if (volume > 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } } else { long volumeTmp = 0; if (!bars.IsNewSession(time, isRealtime)) { volumeTmp = Math.Min(bars.Period.Value - bars.GetVolume(bars.Count - 1), volume); if (volumeTmp > 0) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volumeTmp, isRealtime); } } volumeTmp = volume - volumeTmp; while (volumeTmp > 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, Math.Min(volumeTmp, bars.Period.Value), isRealtime); volumeTmp -= bars.Period.Value; } } break; case PeriodType.Month: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeMonth(time, bars.Period.Value), volume, isRealtime); } else { if ((time.Month <= bars.TimeLastBar.Month && time.Year == bars.TimeLastBar.Year) || time.Year < bars.TimeLastBar.Year) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, isRealtime); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeMonth(time, bars.Period.Value), volume, isRealtime); } } break; case PeriodType.Second: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, 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.Value), volume, isRealtime); } else { if ((bars.Period.Value > 1 && time < bars.TimeLastBar) || (bars.Period.Value == 1 && time <= bars.TimeLastBar)) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, isRealtime); } else { time = TimeToBarTimeSecond(bars, time, bars.Session.NextBeginTime, bars.Period.Value); AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } } break; case PeriodType.Tick: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } else { if (bars.Count > 0 && !bars.IsNewSession(time, isRealtime) && bars.Period.Value > 1 && bars.TickCount < bars.Period.Value) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, time, volume, isRealtime); } } break; case PeriodType.Week: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeWeek(time, time.AddDays((6 - (((int)time.DayOfWeek + 1) % 7)) + ((bars.Period.Value - 1) * 7)), bars.Period.Value), volume, isRealtime); } else if (time.Date <= bars.TimeLastBar.Date) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, isRealtime); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeWeek(time.Date, bars.TimeLastBar.Date, bars.Period.Value), volume, isRealtime); } break; case PeriodType.Year: if (bars.Count == 0) { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeYear(time, bars.Period.Value), volume, isRealtime); } else { if (time.Year <= bars.TimeLastBar.Year) { UpdateBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, bars.TimeLastBar, volume, isRealtime); } else { AddBar(bars, 0 - open, 0 - low, 0 - high, 0 - close, TimeToBarTimeYear(time.Date, bars.Period.Value), volume, isRealtime); } } break; default: break; } #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); } #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 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(); }
/// <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 }