protected override void HandleOrderTriggered(Bar bar, double targetPrice) { double targetQuantity = 0; // While closing sometimes it places duplicate orders which triggers // unwanted reverse positions RefreshOpenQuantity(true); if (GetAbsoluteOpenQuantity() <= 0) // This means the order was already processed by other thread return; targetQuantity = GetTargetQuantity(); if (targetPrice <= 0 || targetQuantity <= 0) throw new ApplicationException( string.Format("Invalid price of quantity calculated. Price {0:c}, Qty {1}", targetPrice, targetQuantity)); string orderName = GetAutoPlacedOrderName(TargetOrderType, EffectiveOrderSide, "Auto-Closed", Instrument.Symbol, EffectiveOrderRetriesConsumed, IbBrokerAccountNumber); base.PlaceTargetOrder(targetQuantity, targetPrice, orderName); LoggingUtility.LogOrder(LoggingConfig, orderName, EffectiveOrderSide, targetQuantity, targetPrice, EffectiveOrderRetriesConsumed); }
public override void OnBarOpen(Bar bar) { try { if (!IsItOkToHandleBar(bar)) { return; } LoggingUtility.WriteTraceFormat(this, "OnBarOpen. {0}", bar); if (bar.Size == PeriodConstants.PERIOD_DAILY) { // Since we will like to capture any gaps in the current day // open and corresponding effects of ATR calculations OnBar(bar); } else if (bar.BeginTime >= CurrentStartOfSessionTime) { //EvaluateIndicatorsAtBeginningOfSession(); OnBar(bar); } base.OnBarOpen(bar); } catch (Exception ex) { LoggingUtility.WriteError(this, ex, "Error in OnBarOpen"); } }
internal double GetEffectiveAllowedSlippage(Bar bar) { if (Instrument.Type != InstrumentType.Stock) return 0; if (TargetOrderType == OrderType.Market) return 0; double timeDifferenceInSessionClose = GetSecondsLeftInSessionEnd(bar); double returnValue = EffectiveMaxAllowedSlippage; double differencePer30Minutes = (EffectiveMaxAllowedSlippage - EffectiveMinAllowedSlippage) / 12; double timeDifferenceInMinutes = timeDifferenceInSessionClose / 60; int halfHourPeriodsLeft = Convert.ToInt32(Math.Floor(timeDifferenceInMinutes / 30)); if (halfHourPeriodsLeft > 12) halfHourPeriodsLeft = 12; if (halfHourPeriodsLeft < 0) halfHourPeriodsLeft = 0; returnValue = EffectiveMaxAllowedSlippage - (differencePer30Minutes * halfHourPeriodsLeft); LoggingUtility.WriteDebug(LoggingConfig, string.Format( "Calculated allowed slippage: {0}. [Min: {1}. Max: {2}. Half Hour Period {3}]", returnValue, EffectiveMinAllowedSlippage, EffectiveMaxAllowedSlippage, halfHourPeriodsLeft)); return returnValue; }
internal static void LogCurrentBarArrival(LoggingConfig config, Bar bar) { if (config.IsDebugEnabled) { string message = string.Format("Bar with begin time {0} arrived: {1}", bar.BeginTime, bar); WriteDebug(config, message); } }
public override double this [Bar bar] { get { this.Init(); return base[bar]; } }
internal static void LogOkToTriggerOrder(LoggingConfig config, Bar bar) { if (config.IsInfoEnabled) { string message = string.Format("It is OK to trigger the trade @ bar: {0}", bar); Console.WriteLine(); WriteInfo(config, message); } }
public override void OnBar(Bar bar) { DateTime time = Clock.Now; int dateTime = time.Hour * 10000 + time.Minute * 100 + time.Second; if (dateTime > closeTime) { ClosePosition("T|尾盘平仓"); return; } if (86400 == bar.Size) { return; } if (double.IsNaN(UpLine)) return; UpSeries.Add(bar.DateTime, UpLine); DownSeries.Add(bar.DateTime, DownLine); RangeSeries.Add(bar.DateTime, Range); if (Mode == StrategyMode.Simulation) { // 从模拟切换实盘时用 //return; } if (HasPosition) { if (Position.Amount < 0 && bar.Close > UpLine) { ClosePosition("T|反手"); Buy(Qty, "O|"); } if (Position.Amount > 0 && bar.Close < DownLine) { ClosePosition("T|反手"); Sell(Qty, "O|"); } } else { if (bar.Close > UpLine) { Buy(Qty, "O|"); } else if (bar.Close < DownLine) { Sell(Qty, "O|"); } } }
public override void OnBar(Bar bar) { if (bStopStrategy) { Console.WriteLine("OnBar"); StopStrategy(); } Console.WriteLine(bar); }
/// <summary> /// /// </summary> /// <param name="bar"></param> protected override void HandleBarOpen(Bar bar) { if (IsItTimeToTrigger(bar, false)) { if (stopPrice.HasValue) { double lastClosePrice = bar.Close; if (StopPriceManager.IsEntryStopPriceMet(lastClosePrice, stopPrice.Value, OrderSide)) { LoggingUtility.LogCurrentBarArrival(LoggingConfig, bar); PriceCalculator priceCalc = new PriceCalculator(LoggingConfig); double targetPrice = priceCalc.CalculateSlippageAdjustedPrice(new PriceCalculatorInput() { AllowedSlippage = AllowedSlippage, Atr = GetAtrValue(Instrument, AtrPeriod, triggerTime.Value), CurrentBar = bar, PreviousBar = GetPreviousBar(Instrument, bar, PeriodConstants.PERIOD_MINUTE), OrderSide = OrderSide }); double targetQuantity = new QuantityCalculator(LoggingConfig).Calculate(new QuantityCalculatorInput() { MaxPortfolioRisk = MaxPortfolioRisk, MaxPositionRisk = MaxPositionRisk, NumberOfPositions = NumberOfPositions, PortfolioAmt = PortfolioAmount, PortfolioAllocationPercentage = PortfolioAllocationPercentage, PositionSizePercentage = PositionSizePercentage, RoundLots = RoundLots, StopPercentage = StopPercentage, TargetPrice = targetPrice }); targetPrice = priceCalc.RoundPrice(targetPrice, Instrument); if (targetPrice <= 0 || targetQuantity <= 0) throw new ApplicationException(string.Format("Invalid price of quantity calculated. Price {0:c}, Qty {1}", targetPrice, targetQuantity)); string orderName = GetAutoPlacedOrderName(OrderSide, string.Format("Auto-Open Stop Order @ {0:c}", stopPrice.Value), Instrument.Symbol); strategyOrder = CreateOrder(OrderSide, targetQuantity, orderName, targetPrice); LoggingUtility.LogOrder(LoggingConfig, orderName, OrderSide, targetQuantity, targetPrice, retryCount); if (AutoSubmit) strategyOrder.Send(); } } } }
/// <summary> /// /// </summary> /// <param name="bar"></param> protected virtual void HandleBarOpen(Bar bar) { if (RetryOrder(bar, HandleStrategyStart)) { LoggingUtility.LogRetryOrder(LoggingConfig, bar, retryCount); } if (IsItTimeToTrigger(bar, true)) { PriceCalculator priceCalc = new PriceCalculator(LoggingConfig); QuantityCalculator qtyCalc = new QuantityCalculator(LoggingConfig); double targetPrice = priceCalc.Calculate(new PriceCalculatorInput() { CurrentBar = Bar, PreviousBar = GetPreviousBar(Instrument, bar, PeriodConstants.PERIOD_MINUTE), Atr = GetAtrValue(Instrument, AtrPeriod, triggerTime.Value), AllowedSlippage = AllowedSlippage, FavorableGap = FavorableGap, FavorableGapAllowedSlippage = FavorableGapAllowedSlippage, UnfavorableGap = UnfavorableGap, UnfavorableGapAllowedSlippage = UnfavorableGapAllowedSlippage, OrderSide = OrderSide }); double targetQuantity = qtyCalc.Calculate(new QuantityCalculatorInput() { NumberOfPositions = NumberOfPositions, PortfolioAmt = PortfolioAmount, PortfolioAllocationPercentage = PortfolioAllocationPercentage, MaxPortfolioRisk = MaxPortfolioRisk, MaxPositionRisk = MaxPositionRisk, RoundLots = RoundLots, TargetPrice = targetPrice, StopPercentage = StopPercentage, PositionSizePercentage = PositionSizePercentage }); targetPrice = priceCalc.RoundPrice(targetPrice, Instrument); if (targetPrice <= 0 || targetQuantity <= 0) throw new ApplicationException(string.Format("Invalid price of quantity calculated. Price {0:c}, Qty {1}", targetPrice, targetQuantity)); string orderName = GetAutoPlacedOrderName(OrderSide, "Auto-Opened", Instrument.Symbol); strategyOrder = CreateOrder(OrderSide, targetQuantity, orderName, targetPrice); LoggingUtility.LogOrder(LoggingConfig, orderName, OrderSide, targetQuantity, targetPrice, retryCount); if (AutoSubmit) strategyOrder.Send(); } }
/* protected void ReloadDailyData() { DateTime start = DateTime.Now; DailyBarSeries = GetHistoricalBars("IB", Instrument, DateTime.Now.AddDays(-60), DateTime.Now, PeriodConstants.PERIOD_DAILY); DateTime end = DateTime.Now; LoggingUtility.WriteDebug(LoggingConfig, string.Format("Took {0}ms to retrieve data from IB for daily data", end.Subtract(start).TotalMilliseconds)); start = DateTime.Now; foreach (Bar currentBar in DailyBarSeries) { Bars.Add(currentBar); if (PersistHistoricalData) DataManager.Add(Instrument, currentBar); } end = DateTime.Now; LoggingUtility.WriteVerbose(LoggingConfig, string.Format("Took {0}ms to load data into memory for daily data", end.Subtract(start).TotalMilliseconds)); }*/ protected Bar GetPreviousBar(Bar bar, int period) { Bar retVal = null; BarSeries barsToUse = null; bool isSessionOpenBar = bar.IsSessionOpenBar(Instrument.Type); bool isDailyPeriod = period == PeriodConstants.PERIOD_DAILY; if (isDailyPeriod) return GetPreviousDayBar(); barsToUse = MinutelyBarSeries; if (barsToUse.Count > 0) { int idx = 0; bool found = false; while (!found && idx <= barsToUse.Count - 1) { Bar prevBar = barsToUse.Ago(idx); if ((prevBar.EndTime <= bar.BeginTime) && prevBar.IsWithinRegularTradingHours(Instrument.Type)) { if (isSessionOpenBar || isDailyPeriod) { found = DateTime.Today.Subtract(prevBar.BeginTime.Date).TotalDays >= 1; if (!found && DateTime.Now.IsPastRegularTradingHours(Instrument.Type)) found = DateTime.Today.Subtract(prevBar.BeginTime.Date).TotalDays >= 0; } else { found = true; } } if (found) retVal = prevBar; else idx++; } } if (retVal == null) throw new ApplicationException(string.Format("Count not retreive a period {0} bar to {1}. If it is due to exchange holidays - then set the 'DaysToGoBackForMinutelyData' parameter to fetch more data.", period, bar)); LoggingUtility.WriteInfo(LoggingConfig, string.Format("Previous closing bar was {0}", retVal)); return retVal; }
protected override void HandleOrderTriggered(Bar bar, double targetPrice) { double targetQuantity = GetTargetQuantity(targetPrice); if (targetPrice <= 0 || targetQuantity <= 0) throw new ApplicationException(string.Format("Invalid price of quantity calculated. Price {0:c}, Qty {1}", targetPrice, targetQuantity)); string orderName = GetAutoPlacedOrderName(TargetOrderType, EffectiveOrderSide, "Auto-Opened", Instrument.Symbol, EffectiveOrderRetriesConsumed, IbBrokerAccountNumber); base.PlaceTargetOrder(targetQuantity, targetPrice, orderName); LoggingUtility.LogOrder(LoggingConfig, orderName, OrderSide, targetQuantity, targetPrice, EffectiveOrderRetriesConsumed); }
private void ProcessAndPlaceOrder(Bar bar) { double targetPrice = GetTargetPrice(bar); EffectiveLastOrderDateTime = DateTime.Now; EffectiveLastOrderPrice = targetPrice; EffectiveOrderRetriesConsumed++; UpdateRetrialStopPrice(bar); SetParamsForRetrialOrder(); HandleOrderTriggered(bar, targetPrice); }
public override void OnBar(Bar bar) { if (bar.Size == 86400) return; if (lbd.Count < 1 || dbbu.Count < 1) return; int lookBackDaysInt = (int)lbd.Last; int nEnd = bars86400.Count - 1; int nBegin = nEnd - lookBackDays + 1; double buyPoint = bars86400.HighestHigh(nBegin, nEnd); double sellPoint = bars86400.LowestLow(nBegin, nEnd); double longLiqPoint = dbbu.SMA.Last; double shortLiqPoint = dbbu.SMA.Last; double upBand = dbbu.Last; double dnBand = dbbu.BBL.Last; upBandSeries.Add(bar.DateTime, upBand); dnBandSeries.Add(bar.DateTime, dnBand); buyPointSeries.Add(bar.DateTime, buyPoint); sellPointSeries.Add(bar.DateTime, sellPoint); // 下面代码可能有问题 if (HasPosition) { if (Position.Amount > 0 && Bar.Close < longLiqPoint) { ClosePosition("T|"); } if (Position.Amount < 0 && Bar.Close > shortLiqPoint) { ClosePosition("T|"); } } else { if (Bar.Close > upBand)// && Bar.Close >= buyPoint { Buy(Qty, "O|"); } if (Bar.Close < dnBand)// && Bar.Close <= sellPoint { Sell(Qty, "O|"); } } }
protected void SaveData(Bar bar) { DataManager.Add(this.Instrument, bar); DataManager.Flush(); if (bar.Size == CurrentExecutionTimePeriodInSeconds) { CurrentExecutionBarSeries.Add(bar); } if (bar.Size == PeriodConstants.PERIOD_DAILY) { CurrentDailyBarSeries.Add(bar); } }
public override Bar FilterBarOpen(Bar bar, string symbol) { _bar_trade[symbol] = new Trade(Clock.Now, bar.Close, (int)bar.Volume); Trade t1, t2; if (_bar_trade.TryGetValue("AAPL", out t1) && _bar_trade.TryGetValue("MSFT", out t2)) { EmitTrade("AAPL-MSFT", Clock.Now, t1.Price - t2.Price, 0); } // 注意,这个地方要返回 // 不修改默认行情 return bar; }
public double GetSecondsLeftInSessionEnd(Bar bar) { double timeDifferenceInSessionClose = 0; if (bar.BeginTime.IsWithinRegularTradingHours(Instrument.Type) && bar.BeginTime >= EffectiveStartOfSessionTime) { timeDifferenceInSessionClose = Math.Abs((new DateTime(ValidityTriggerDate.Date.Year, ValidityTriggerDate.Date.Month, ValidityTriggerDate.Date.Day) .AddSeconds(PstSessionTimeConstants.StockExchangeEndTimeSeconds) .Subtract(bar.BeginTime)).TotalSeconds); } return timeDifferenceInSessionClose; }
public override void OnBarOpen(Bar bar) { if (!bar.IsWithinRegularTradingHours(Instrument.Type)) { return; } if (bar.Size == PeriodConstants.PERIOD_DAILY) { return; } PublishOpenBar(bar); base.OnBarOpen(bar); }
public override Bar FilterBarOpen(Bar bar, string symbol) { string key = string.Format("{0}.{1}.{2}", symbol, bar.Type, bar.Size); _bars[key] = bar; // 在这之前可以做自己的过滤 Bar b = bar; if (filter != null) { b = filter.FilterBarOpen(bar, symbol); } if (b != null) { EmitBarOpen(symbol, b.DateTime, b.Open, b.High, b.Low, b.Close, b.Volume, b.OpenInt, b.Size); } else { return null; } Bar b1, b2; string key1 = string.Format("{0}.{1}.{2}", "l1405", bar.Type, bar.Size); string key2 = string.Format("{0}.{1}.{2}", "v1405", bar.Type, bar.Size); if ("l1405-v1405".Contains(symbol)) { if (_bars.TryGetValue(key1, out b1) && _bars.TryGetValue(key2, out b2)) { // 这个地方一定要注意!!!!b1.High与b2.High由于发生的时间点不同,相减得到的High是不正确的 // 如果还用他来计算TR和ATR指标的话,那就更加有问题了,Low原理也是一样 // 如果没有用到High/Low,直接用0也不合适,图表显示会乱 EmitBar("l1405-v1405", bar.DateTime, b1.Open - b2.Open, Math.Max(b1.Open - b2.Open, b1.Close - b2.Close), Math.Min(b1.Open - b2.Open, b1.Close - b2.Close), b1.Close - b2.Close, 0, 0, bar.Size); } } // 注意,这个地方一定要返回null // 这实际上是让插件内部的Emit不调用 return null; }
public override void OnBar(Bar bar) { do { // 尾盘平仓 if (0 != ExitOnClose(60,"")) break; // 日线数据上不处理 if (86400 == bar.Size) break; // 数据 if (double.IsNaN(UpLine)) break; UpSeries.Add(bar.DateTime, UpLine); DownSeries.Add(bar.DateTime, DownLine); RangeSeries.Add(bar.DateTime, Range); if (bar.Close > UpLine) { TargetPosition = 1; TextParameter.Text = "突破上轨,多头"; } else if (bar.Close < DownLine) { TargetPosition = -1; TextParameter.Text = "突破下轨,空头"; } else { // 处于中间状态的怎么处理? } } while (false); if (Mode == StrategyMode.Simulation) { // 从模拟切换实盘时用 //return; } base.OnBar(bar); }
protected virtual void OnBarOpenReceived(Bar bar) { if (!IsBarValid(bar)) { LoggingUtility.WriteWarn(LoggingConfig, "Discarding an invalid Bar. waiting for next bar."); return; } ProcessSessionOpeningBarIfRequired(bar); AutoCalculateRetrialParamsIfRequired(bar); if (!IsValidityTimeTriggered && bar.BeginTime >= EffectiveValidityTriggerTime) { IsValidityTimeTriggered = true; LoggingUtility.LogOkToTriggerOrder(LoggingConfig, bar); EffectiveOriginalOpeningPriceAtStartOfStrategy = EffectiveOpenPrice; } RecalculateStopPriceBasedOnNewHiLoForTheDay(bar); bool openingGapTriggered = EffectiveOpeningSessionBarAlreadyProcessed && CanOrderBeTriggeredAtOpeningGap() && DidOpeningGapStopPriceTriggered(bar, "Opening Gap Stop Test"); if (IsValidityTimeTriggered || openingGapTriggered) { LoggingUtility.LogCurrentBarArrival(LoggingConfig, bar); EffectiveImmediatePastQuotePrice = EffectiveQuotePrice; EffectiveQuotePrice = bar.Open; if (EffectiveQuotePrice <= 0) EffectiveQuotePrice = bar.Close; EffectiveChangeInPrice = EffectiveQuotePrice - EffectivePreviousClosePrice; CheckIfIwmStopPriceHasTriggered(bar); HandleBarOpened(bar); TriggerOrderIfRequired(bar); } }
/// <summary> /// /// </summary> /// <param name="bar"></param> public virtual void HandleBarOpen(Bar bar) { if (bar.BeginTime >= triggerTime) { if (openPrice == null) { openPrice = bar.Open; } if (!HasPosition && closingOrder == null) { OrderSide? side = null; double targetPrice = openPrice.Value; double targetQuantity = 0; if (longPositionQuantity.HasValue && longPositionQuantity.Value > 0) { side = OrderSide.Sell; targetPrice = GetSlippageAdjustedPrice(openPrice.Value, side.Value); targetQuantity = longPositionQuantity.Value; } if (shortPositionQuantity.HasValue && shortPositionQuantity.Value > 0) { side = OrderSide.Buy; targetPrice = GetSlippageAdjustedPrice(openPrice.Value, side.Value); targetQuantity = shortPositionQuantity.Value; } targetPrice = RoundPrice(targetPrice); if (side.HasValue) { closingOrder = LimitOrder(side.Value, targetQuantity, targetPrice, "Auto closing order"); LogOrder("Closing", Instrument.Symbol, side.Value, targetQuantity, targetPrice); if (AutoSubmit) closingOrder.Send(); } } } }
/// <summary> /// /// </summary> /// <param name="bar"></param> protected void AutoCalculateRetrialParamsIfRequired(Bar bar) { if (OrderTriggerStrategy == OrderTriggerStrategy.TimerBasedTrigger) return; if (OrderRetrialStrategy == Enums.OrderRetrialStrategy.None) return; double timeDifferenceInSessionClose = GetSecondsLeftInSessionEnd(bar); if (timeDifferenceInSessionClose <= 0) return; if (alreadyAutoCalculatedRetries) return; int maxRetriesToBeAccomodated = Convert.ToInt32(Math.Floor(timeDifferenceInSessionClose/EffectiveRetryIntervalInSeconds)); if (MaximumRetries > maxRetriesToBeAccomodated) { if (maxRetriesToBeAccomodated <= 0) { maxRetriesToBeAccomodated = 1; if (EffectiveRetryIntervalInSeconds > (timeDifferenceInSessionClose - 120)) EffectiveRetryIntervalInSeconds = Math.Abs((timeDifferenceInSessionClose - 120)); } LoggingUtility.WriteInfo(LoggingConfig, string.Format( "Changing the maximum retry count to {0} from {1} because only {0} retries can be accomodated at an interval of {2} with {3} seconds remaining in the close.", maxRetriesToBeAccomodated, MaximumRetries, EffectiveRetryIntervalInSeconds, timeDifferenceInSessionClose )); MaximumRetries = maxRetriesToBeAccomodated; } alreadyAutoCalculatedRetries = true; }
public override void OnBar(Bar bar) { TargetOrderBook.Sell.Set(300, 10); TargetOrderBook.Sell.Set(200, 5); TargetOrderBook.Buy.Set(100, 10); TargetOrderBook.Buy.Set(50, 10); // 设置目标订单列表 // 对比订单列表 // 撤单,防止自成交 // 同一价位,如果全是自己挂的,可以先撤开仓单 // 不是自己挂的,先撤后挂的 // 按数量开仓 // 先撤交集, // 挂指定价格单 // 调整后面的价格与数量 // 由于后面的价格与数量没有啥影响,所以基本不调,先撤单 }
public void ProcessBar(Bar bar) { try { if (!IsItOkToHandleBar(bar)) { return; } if (bar.BeginTime >= CurrentValidityDateTime && !AreAllLegsCompleted) { LoggingUtility.WriteTraceFormat(this, "Processing bar: {0}", bar); } BasicSaveBar(bar); CurrentBarRef = bar; SetCurrentDayOpeningPrice(bar); SetCurrentLastPrice(bar); if (bar.Size == CurrentExecutionTimePeriodInSeconds) { int[] periods = new[] { SlowMaPeriod, FastMaPeriod, StochasticsDPeriod, StochasticsKPeriod, StochasticsSmoothPeriod }; int maxPeriod = periods.Max(); if (CurrentExecutionBarSeries.Count <= maxPeriod) { return; } // Ensure that intraday indicators are evaluated GetIsStochInBullishMode(bar); GetIsStochInBearishMode(bar); GetIsEmaInBearishMode(bar); GetIsEmaInBullishMode(bar); GetIsEmaAlmostInBearishMode(bar); GetIsEmaAlmostInBullishMode(bar); GetIsStochInObMode(bar); GetIsStochInOsMode(bar); AttempOrder(); } } catch (Exception ex) { LoggingUtility.WriteError(this, ex, "Error in ProcessBar"); } finally { CurrentBarRef = null; } }
private void SetCurrentLastPrice(Bar bar) { if (bar.BeginTime >= CurrentStartOfSessionTime && !AreAllLegsCompleted) { if ( bar.Close > 0) { CurrentLastPrice = bar.Close; WriteInfrequentDebugMessage(string.Format("Setting last price for {0:c2}", CurrentLastPrice)); } } }
private void SetCurrentDayOpeningPrice(Bar bar) { if (bar.BeginTime >= CurrentStartOfSessionTime) { if (CurrentDayOperningPrice <= 0 && bar.Open > 0) { CurrentDayOperningPrice = bar.Open; LoggingUtility.WriteInfoFormat(this, "Setting opening price for today {0:c2}", CurrentDayOperningPrice); } } }
private bool IsBarCloseEnoughForLogging(Bar bar) { long barSize = bar.Size; if (barSize == PeriodConstants.PERIOD_DAILY) { return (CurrentValidityDateTime.Subtract(bar.BeginTime.Date).TotalDays <= 7); } if (!IsCurrentOrderActive()) return false; if (bar.BeginTime >= CurrentValidityDateTime) return true; return (bar.BeginTime >= CurrentLastSessionDate.Date.AddHours(12)); }
private void BasicSaveBar(Bar bar) { SaveData(bar); CurrentClosePrice = bar.Close; }
protected bool IsItOkToHandleBar(Bar bar) { if (!bar.IsWithinRegularTradingHours(Instrument.Type)) { LoggingUtility.WriteTraceFormat(this, "Bar is not within regular trading hours: {0}", bar); return false; } return true; }
public virtual Bar FilterBarOpen(Bar bar, string symbol) { return(bar); }