/// <summary> /// Constructor for the CFD security /// </summary> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="config">The subscription configuration for this security</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Cfd(SecurityExchangeHours exchangeHours, Cash quoteCurrency, SubscriptionDataConfig config, SymbolProperties symbolProperties) : base(config, quoteCurrency, symbolProperties, new CfdExchange(exchangeHours), new CfdCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new ConstantFeeModel(0), new SpreadSlippageModel(), new ImmediateSettlementModel(), new SecurityMarginModel(50m), new CfdDataFilter() ) { Holdings = new CfdHolding(this); }
/// <summary> /// Constructor for the CFD security /// </summary> /// <param name="symbol">The security's symbol</param> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Cfd(Symbol symbol, SecurityExchangeHours exchangeHours, Cash quoteCurrency, SymbolProperties symbolProperties) : base(symbol, quoteCurrency, symbolProperties, new CfdExchange(exchangeHours), new CfdCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new ConstantFeeModel(0), new SpreadSlippageModel(), new ImmediateSettlementModel(), Securities.VolatilityModel.Null, new SecurityMarginModel(50m), new CfdDataFilter() ) { Holdings = new CfdHolding(this); }
/// <summary> /// Construct the Equity Object /// </summary> public Equity(Symbol symbol, SecurityExchangeHours exchangeHours, Cash quoteCurrency, SymbolProperties symbolProperties) : base(symbol, quoteCurrency, symbolProperties, new EquityExchange(exchangeHours), new EquityCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new InteractiveBrokersFeeModel(), new ConstantSlippageModel(0m), new ImmediateSettlementModel(), Securities.VolatilityModel.Null, new SecurityMarginModel(2m), new EquityDataFilter() ) { Holdings = new EquityHolding(this); }
/// <summary> /// Constructor for the option security /// </summary> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="config">The subscription configuration for this security</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Option(SecurityExchangeHours exchangeHours, SubscriptionDataConfig config, Cash quoteCurrency, SymbolProperties symbolProperties) : base(config, quoteCurrency, symbolProperties, new OptionExchange(exchangeHours), new OptionCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new InteractiveBrokersFeeModel(), new SpreadSlippageModel(), new ImmediateSettlementModel(), Securities.VolatilityModel.Null, new SecurityMarginModel(2m), new OptionDataFilter() ) { PriceModel = new CurrentPriceOptionPriceModel(); ContractFilter = new StrikeExpiryOptionFilter(-5, 5, TimeSpan.Zero, TimeSpan.FromDays(35)); }
/// <summary> /// Constructor for the forex security /// </summary> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="config">The subscription configuration for this security</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Forex(SecurityExchangeHours exchangeHours, Cash quoteCurrency, SubscriptionDataConfig config, SymbolProperties symbolProperties) : base(config, quoteCurrency, symbolProperties, new ForexExchange(exchangeHours), new ForexCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new InteractiveBrokersFeeModel(), new SpreadSlippageModel(), new ImmediateSettlementModel(), new SecurityMarginModel(50m), new ForexDataFilter() ) { Holdings = new ForexHolding(this); // decompose the symbol into each currency pair string baseCurrencySymbol, quoteCurrencySymbol; DecomposeCurrencyPair(config.Symbol.Value, out baseCurrencySymbol, out quoteCurrencySymbol); BaseCurrencySymbol = baseCurrencySymbol; }
/// <summary> /// Constructor for the CFD security /// </summary> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="config">The subscription configuration for this security</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Cfd(SecurityExchangeHours exchangeHours, Cash quoteCurrency, SubscriptionDataConfig config, SymbolProperties symbolProperties) : base(config, new CfdExchange(exchangeHours), new CfdCache(), new CfdPortfolioModel(), new ImmediateFillModel(), new ConstantFeeModel(0), new SpreadSlippageModel(), new ImmediateSettlementModel(), new CfdMarginModel(50m), new CfdDataFilter() ) { QuoteCurrency = quoteCurrency; Holdings = new CfdHolding(this); SymbolProperties = symbolProperties; if (symbolProperties == null) throw new ArgumentException("CFD requires a valid SymbolProperties argument"); if (symbolProperties.QuoteCurrency != quoteCurrency.Symbol) throw new ArgumentException("CFD SymbolProperties.QuoteCurrency and QuoteCurrency.Symbol do not match."); }
/// <summary> /// Creates a subscription to process the request /// </summary> private Subscription CreateSubscription(HistoryRequest request, DateTime startUtc, DateTime endUtc) { // data reader expects these values in local times var startTimeLocal = startUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var endTimeLocal = endUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); _dataPermissionManager.AssertConfiguration(config); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var mapFileResolver = MapFileResolver.Empty; if (config.TickerShouldBeMapped()) { mapFileResolver = _mapFileProvider.Get(config.Market); var mapFile = mapFileResolver.ResolveMapFile(config.Symbol.ID.Symbol, config.Symbol.ID.Date); config.MappedSymbol = mapFile.GetMappedSymbol(startTimeLocal, config.MappedSymbol); } // Tradable dates are defined with the data time zone to access the right source var tradableDates = Time.EachTradeableDayInTimeZone(request.ExchangeHours, startTimeLocal, endTimeLocal, request.DataTimeZone, request.IncludeExtendedMarketHours); var dataReader = new SubscriptionDataReader(config, startTimeLocal, endTimeLocal, mapFileResolver, _factorFileProvider, tradableDates, false, _dataCacheProvider ); dataReader.InvalidConfigurationDetected += (sender, args) => { OnInvalidConfigurationDetected(args); }; dataReader.NumericalPrecisionLimited += (sender, args) => { OnNumericalPrecisionLimited(args); }; dataReader.StartDateLimited += (sender, args) => { OnStartDateLimited(args); }; dataReader.DownloadFailed += (sender, args) => { OnDownloadFailed(args); }; dataReader.ReaderErrorDetected += (sender, args) => { OnReaderErrorDetected(args); }; IEnumerator <BaseData> reader = dataReader; var intraday = GetIntradayDataEnumerator(dataReader, request); if (intraday != null) { // we optionally concatenate the intraday data enumerator reader = new ConcatEnumerator(true, reader, intraday); } reader = CorporateEventEnumeratorFactory.CreateEnumerators( reader, config, _factorFileProvider, dataReader, mapFileResolver, startTimeLocal); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, request.IncludeExtendedMarketHours, endTimeLocal, config.Increment, config.DataTimeZone); } // since the SubscriptionDataReader performs an any overlap condition on the trade bar's entire // range (time->end time) we can end up passing the incorrect data (too far past, possibly future), // so to combat this we deliberately filter the results from the data reader to fix these cases // which only apply to non-tick data reader = new SubscriptionFilterEnumerator(reader, security, endTimeLocal, config.ExtendedMarketHours, false, request.ExchangeHours); reader = new FilterEnumerator <BaseData>(reader, data => { // allow all ticks if (config.Resolution == Resolution.Tick) { return(true); } // filter out all aux data if (data.DataType == MarketDataType.Auxiliary) { return(false); } // filter out future data if (data.EndTime > endTimeLocal) { return(false); } // filter out data before the start return(data.EndTime > startTimeLocal); }); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, request.StartTimeUtc, request.EndTimeUtc); if (_parallelHistoryRequestsEnabled) { return(SubscriptionUtils.CreateAndScheduleWorker(subscriptionRequest, reader, _factorFileProvider, false)); } return(SubscriptionUtils.Create(subscriptionRequest, reader)); }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataProvider dataProvider, IDataFeedSubscriptionManager subscriptionManager) { if (!(job is LiveNodePacket)) { throw new ArgumentException("The LiveTradingDataFeed requires a LiveNodePacket."); } _cancellationTokenSource = new CancellationTokenSource(); _algorithm = algorithm; _job = (LiveNodePacket)job; _resultHandler = resultHandler; _timeProvider = GetTimeProvider(); _dataQueueHandler = GetDataQueueHandler(); _dataProvider = dataProvider; _dataCacheProvider = new SingleEntryDataCacheProvider(dataProvider); _frontierTimeProvider = new ManualTimeProvider(_timeProvider.GetUtcNow()); _customExchange = new BaseDataExchange("CustomDataExchange") { SleepInterval = 10 }; // sleep is controlled on this exchange via the GetNextTicksEnumerator _exchange = new BaseDataExchange("DataQueueExchange") { SleepInterval = 0 }; _exchange.AddEnumerator(DataQueueHandlerSymbol, GetNextTicksEnumerator()); _subscriptions = subscriptionManager.DataFeedSubscriptions; _bridge = new BusyBlockingCollection <TimeSlice>(); _universeSelection = new UniverseSelection(this, algorithm); // run the exchanges Task.Run(() => _exchange.Start(_cancellationTokenSource.Token)); Task.Run(() => _customExchange.Start(_cancellationTokenSource.Token)); // wire ourselves up to receive notifications when universes are added/removed var start = _timeProvider.GetUtcNow(); algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } AddSubscription(new SubscriptionRequest(true, universe, security, config, start, Time.EndOfTime)); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
public void NonUsdAccountCurrencyCurrencyDataFeedsGetAdded(string accountCurrency, string quoteCurrency, string baseCurrency, string quoteCurrencySymbol, string baseCurrencySymbol, SecurityType securityType, string market) { var quoteCash = new Cash(quoteCurrency, 100, 1); var baseCash = new Cash(baseCurrency, 100, 1); var cashBook = new CashBook { { quoteCurrency, quoteCash }, { baseCurrency, baseCash } }; var symbol = Symbol.Create(baseCurrency + quoteCurrency, securityType, market); var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper) { { symbol, new Security( SecurityExchangeHours, subscriptions.Add(symbol, Resolution.Minute, TimeZone, TimeZone), new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) } }; var configs1 = quoteCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.AreEqual(1, configs1.Count); var config1 = configs1[0]; Assert.IsNotNull(config1); Assert.AreEqual(quoteCurrencySymbol, config1.Symbol.Value); var configs2 = baseCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.AreEqual(1, configs2.Count); var config2 = configs2[0]; Assert.IsNotNull(config2); Assert.AreEqual(baseCurrencySymbol, config2.Symbol.Value); }
public void NotifiesWhenSecurityRemoved() { var timeKeeper = new TimeKeeper(new DateTime(2015, 12, 07)); var manager = new SecurityManager(timeKeeper); var security = new Security(SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork), CreateTradeBarConfig(), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)); manager.Add(security.Symbol, security); manager.CollectionChanged += (sender, args) => { if (args.OldItems.OfType <object>().Single() != security) { Assert.Fail("Expected args.NewItems to have exactly one element equal to security"); } else { Assert.IsTrue(args.Action == NotifyCollectionChangedAction.Remove); Assert.Pass(); } }; manager.Remove(security.Symbol); }
/// <summary> /// Adds a new subscription for universe selection /// </summary> /// <param name="universe">The universe to add a subscription for</param> /// <param name="startTimeUtc">The start time of the subscription in utc</param> /// <param name="endTimeUtc">The end time of the subscription in utc</param> public void AddUniverseSubscription(Universe universe, DateTime startTimeUtc, DateTime endTimeUtc) { // TODO : Consider moving the creating of universe subscriptions to a separate, testable class // grab the relevant exchange hours var config = universe.Configuration; var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object if it doesn't exist security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } var localStartTime = startTimeUtc.ConvertFromUtc(security.Exchange.TimeZone); var localEndTime = endTimeUtc.ConvertFromUtc(security.Exchange.TimeZone); // define our data enumerator IEnumerator <BaseData> enumerator; var tradeableDates = Time.EachTradeableDayInTimeZone(security.Exchange.Hours, localStartTime, localEndTime, config.DataTimeZone, config.ExtendedMarketHours); var userDefined = universe as UserDefinedUniverse; if (userDefined != null) { // spoof a tick on the requested interval to trigger the universe selection function enumerator = userDefined.GetTriggerTimes(startTimeUtc, endTimeUtc, marketHoursDatabase) .Select(x => new Tick { Time = x, Symbol = config.Symbol }).GetEnumerator(); // route these custom subscriptions through the exchange for buffering var enqueueable = new EnqueueableEnumerator <BaseData>(true); // add this enumerator to our exchange ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution)); enumerator = enqueueable; } else if (config.Type == typeof(CoarseFundamental)) { var cf = new CoarseFundamental(); // load coarse data day by day enumerator = (from date in Time.EachTradeableDayInTimeZone(security.Exchange.Hours, _algorithm.StartDate, _algorithm.EndDate, config.DataTimeZone, config.ExtendedMarketHours) let source = cf.GetSource(config, date, false) let factory = SubscriptionDataSourceReader.ForSource(source, config, date, false) let coarseFundamentalForDate = factory.Read(source) select new BaseDataCollection(date.AddDays(1), config.Symbol, coarseFundamentalForDate) ).GetEnumerator(); var enqueueable = new EnqueueableEnumerator <BaseData>(true); ScheduleEnumerator(enumerator, enqueueable, 5, 100000, 2); enumerator = enqueueable; } else if (config.SecurityType == SecurityType.Option && security is Option) { var configs = universe.GetSubscriptions(security); var enumerators = configs.Select(c => CreateSubscriptionEnumerator(security, c, localStartTime, localEndTime, _mapFileProvider.Get(c.Market), tradeableDates, false, true) ).ToList(); var sync = new SynchronizingEnumerator(enumerators); enumerator = new OptionChainUniverseDataCollectionAggregatorEnumerator(sync, config.Symbol); var enqueueable = new EnqueueableEnumerator <BaseData>(true); // add this enumerator to our exchange ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution)); enumerator = enqueueable; } else { // normal reader for all others enumerator = CreateSubscriptionEnumerator(security, config, localStartTime, localEndTime, MapFileResolver.Empty, tradeableDates, true, false); // route these custom subscriptions through the exchange for buffering var enqueueable = new EnqueueableEnumerator <BaseData>(true); // add this enumerator to our exchange ScheduleEnumerator(enumerator, enqueueable, GetLowerThreshold(config.Resolution), GetUpperThreshold(config.Resolution)); enumerator = enqueueable; } // create the subscription var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, startTimeUtc, endTimeUtc); var subscription = new Subscription(universe, security, config, enumerator, timeZoneOffsetProvider, startTimeUtc, endTimeUtc, true); _subscriptions.TryAdd(subscription); UpdateFillForwardResolution(); }
/// <summary> /// Creates a new instance of the DataManager /// </summary> public DataManager( IDataFeed dataFeed, UniverseSelection universeSelection, IAlgorithm algorithm, ITimeKeeper timeKeeper, MarketHoursDatabase marketHoursDatabase, bool liveMode, IRegisteredSecurityDataTypesProvider registeredTypesProvider, IDataPermissionManager dataPermissionManager) { _dataFeed = dataFeed; UniverseSelection = universeSelection; UniverseSelection.SetDataManager(this); _algorithmSettings = algorithm.Settings; AvailableDataTypes = SubscriptionManager.DefaultDataTypes(); _timeKeeper = timeKeeper; _marketHoursDatabase = marketHoursDatabase; _liveMode = liveMode; _registeredTypesProvider = registeredTypesProvider; _dataPermissionManager = dataPermissionManager; // wire ourselves up to receive notifications when universes are added/removed algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { var config = universe.Configuration; var start = algorithm.UtcTime; var end = algorithm.LiveMode ? Time.EndOfTime : algorithm.EndDate.ConvertToUtc(algorithm.TimeZone); Security security; if (!algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object if it doesn't exist security = new Security( _marketHoursDatabase.GetExchangeHours(config), config, algorithm.Portfolio.CashBook[algorithm.AccountCurrency], SymbolProperties.GetDefault(algorithm.AccountCurrency), algorithm.Portfolio.CashBook, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); } AddSubscription( new SubscriptionRequest(true, universe, security, config, start, end)); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { // removing the subscription will be handled by the SubscriptionSynchronizer // in the next loop as well as executing a UniverseSelection one last time. if (!universe.DisposeRequested) { universe.Dispose(); } } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
public void TestMarginForSymbolWithNoHistory() { const decimal price = 1.2345m; var time = new DateTime(2016, 1, 1); var expDate = new DateTime(2017, 1, 1); var tz = TimeZones.NewYork; // For this symbol we dont have any history at all var ticker = "NOT-A-SYMBOL"; var symbol = Symbol.CreateFuture(ticker, Market.USA, expDate); var futureSecurity = new Future(SecurityExchangeHours.AlwaysOpen(tz), new SubscriptionDataConfig(typeof(TradeBar), symbol, Resolution.Minute, tz, tz, true, false, false), new Cash(CashBook.AccountCurrency, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(CashBook.AccountCurrency))); futureSecurity.SetMarketPrice(new Tick { Value = price, Time = time }); futureSecurity.Holdings.SetHoldings(1.5m, 1); var buyingPowerModel = new TestFutureMarginModel(); Assert.AreEqual(0m, buyingPowerModel.GetMaintenanceMargin(futureSecurity)); }
public override void OnEndOfAlgorithm() { // Reset our Symbol property value, for testing purposes. SymbolPropertiesDatabase.SetEntry(Market.USA, MarketHoursDatabase.GetDatabaseSymbolKey(_bitcoin.Symbol), SecurityType.Base, SymbolProperties.GetDefault("USD")); }
/// <summary> /// Initializes the data feed for the specified job and algorithm /// </summary> public void Initialize(IAlgorithm algorithm, AlgorithmNodePacket job, IResultHandler resultHandler, IMapFileProvider mapFileProvider, IFactorFileProvider factorFileProvider, IDataFileProvider dataFileProvider) { _algorithm = algorithm; _resultHandler = resultHandler; _mapFileProvider = mapFileProvider; _factorFileProvider = factorFileProvider; _dataFileProvider = dataFileProvider; _subscriptions = new SubscriptionCollection(); _universeSelection = new UniverseSelection(this, algorithm, job.Controls); _cancellationTokenSource = new CancellationTokenSource(); IsActive = true; var threadCount = Math.Max(1, Math.Min(4, Environment.ProcessorCount - 3)); _controller = new ParallelRunnerController(threadCount); _controller.Start(_cancellationTokenSource.Token); var ffres = Time.OneMinute; _fillForwardResolution = Ref.Create(() => ffres, res => ffres = res); // wire ourselves up to receive notifications when universes are added/removed algorithm.UniverseManager.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var universe in args.NewItems.OfType <Universe>()) { var config = universe.Configuration; var start = _frontierUtc != DateTime.MinValue ? _frontierUtc : _algorithm.StartDate.ConvertToUtc(_algorithm.TimeZone); var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); var exchangeHours = marketHoursDatabase.GetExchangeHours(config); Security security; if (!_algorithm.Securities.TryGetValue(config.Symbol, out security)) { // create a canonical security object if it doesn't exist security = new Security(exchangeHours, config, _algorithm.Portfolio.CashBook[CashBook.AccountCurrency], SymbolProperties.GetDefault(CashBook.AccountCurrency)); } var end = _algorithm.EndDate.ConvertToUtc(_algorithm.TimeZone); AddSubscription(new SubscriptionRequest(true, universe, security, config, start, end)); } break; case NotifyCollectionChangedAction.Remove: foreach (var universe in args.OldItems.OfType <Universe>()) { RemoveSubscription(universe.Configuration); } break; default: throw new NotImplementedException("The specified action is not implemented: " + args.Action); } }; }
/// <summary> /// Constructor for the forex security /// </summary> /// <param name="symbol">The security's symbol</param> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Forex(Symbol symbol, SecurityExchangeHours exchangeHours, Cash quoteCurrency, SymbolProperties symbolProperties) : base(symbol, quoteCurrency, symbolProperties, new ForexExchange(exchangeHours), new ForexCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new InteractiveBrokersFeeModel(), new ConstantSlippageModel(0), new ImmediateSettlementModel(), Securities.VolatilityModel.Null, new SecurityMarginModel(50m), new ForexDataFilter(), new SecurityPriceVariationModel() ) { Holdings = new ForexHolding(this); // decompose the symbol into each currency pair string baseCurrencySymbol, quoteCurrencySymbol; DecomposeCurrencyPair(symbol.Value, out baseCurrencySymbol, out quoteCurrencySymbol); BaseCurrencySymbol = baseCurrencySymbol; }
/// <summary> /// Constructor for the Future security /// </summary> /// <param name="symbol">The subscription security symbol</param> /// <param name="exchangeHours">Defines the hours this exchange is open</param> /// <param name="quoteCurrency">The cash object that represent the quote currency</param> /// <param name="symbolProperties">The symbol properties for this security</param> public Future(Symbol symbol, SecurityExchangeHours exchangeHours, Cash quoteCurrency, SymbolProperties symbolProperties) : base(symbol, quoteCurrency, symbolProperties, new FutureExchange(exchangeHours), new FutureCache(), new SecurityPortfolioModel(), new ImmediateFillModel(), new InteractiveBrokersFeeModel(), new ConstantSlippageModel(0), new ImmediateSettlementModel(), Securities.VolatilityModel.Null, new FutureMarginBuyingPowerModel(), new SecurityDataFilter(), new SecurityPriceVariationModel() ) { // for now all futures are cash settled as we don't allow underlying (Live Cattle?) to be posted on the account SettlementType = SettlementType.Cash; Holdings = new FutureHolding(this); _symbolProperties = symbolProperties; SetFilter(TimeSpan.Zero, TimeSpan.FromDays(35)); }
public SymbolViewModel(SymbolProperties model, int imageSize) { _model = model; _imageSize = imageSize; }
private Security InitializeTest(DateTime reference, out SecurityPortfolioManager portfolio) { var security = new Security(SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork), CreateTradeBarConfig(), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)); security.SetMarketPrice(new Tick { Value = 100 }); var timeKeeper = new TimeKeeper(reference); var securityManager = new SecurityManager(timeKeeper); securityManager.Add(security); var transactionManager = new SecurityTransactionManager(securityManager); portfolio = new SecurityPortfolioManager(securityManager, transactionManager); portfolio.SetCash("USD", 100 * 1000m, 1m); Assert.AreEqual(0, security.Holdings.Quantity); Assert.AreEqual(100 * 1000m, portfolio.CashBook[CashBook.AccountCurrency].Amount); return(security); }
private static Security CreateSecurity(DateTime newLocalTime) { var security = new Security(CreateUsEquitySecurityExchangeHours(), CreateTradeBarConfig(), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)); TimeKeeper.SetUtcDateTime(newLocalTime.ConvertToUtc(security.Exchange.TimeZone)); security.Exchange.SetLocalDateTimeFrontier(newLocalTime); security.SetLocalTimeKeeper(TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork)); security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, newLocalTime, 100m)); return(security); }
public void TestMarginForSymbolWithHistory() { const decimal price = 1.2345m; var time = new DateTime(2013, 1, 1); var expDate = new DateTime(2017, 1, 1); var tz = TimeZones.NewYork; // For this symbol we dont have history var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar; var symbol = Symbol.CreateFuture(ticker, Market.USA, expDate); var futureSecurity = new Future(SecurityExchangeHours.AlwaysOpen(tz), new SubscriptionDataConfig(typeof(TradeBar), symbol, Resolution.Minute, tz, tz, true, false, false), new Cash(CashBook.AccountCurrency, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(CashBook.AccountCurrency))); futureSecurity.SetMarketPrice(new Tick { Value = price, Time = time }); futureSecurity.Holdings.SetHoldings(1.5m, 1); var buyingPowerModel = new TestFutureMarginModel(); Assert.AreEqual(625m, buyingPowerModel.GetMaintenanceMargin(futureSecurity)); // now we move forward to exact date when margin req changed time = new DateTime(2014, 06, 13); futureSecurity.SetMarketPrice(new Tick { Value = price, Time = time }); Assert.AreEqual(725m, buyingPowerModel.GetMaintenanceMargin(futureSecurity)); // now we fly beyond the last line of the history file (currently) to see how margin model resolves future dates time = new DateTime(2016, 06, 04); futureSecurity.SetMarketPrice(new Tick { Value = price, Time = time }); Assert.AreEqual(585m, buyingPowerModel.GetMaintenanceMargin(futureSecurity)); }
public void LoadsDefaultLotSize() { var defaultSymbolProperties = SymbolProperties.GetDefault(Currencies.USD); Assert.AreEqual(defaultSymbolProperties.LotSize, 1); }
public void RefreshesFutureChainUniverseOnDateChange() { var startTime = new DateTime(2018, 10, 17, 10, 0, 0); var timeProvider = new ManualTimeProvider(startTime); var symbolUniverse = new TestDataQueueUniverseProvider(timeProvider); var factory = new FuturesChainUniverseSubscriptionEnumeratorFactory(symbolUniverse, timeProvider); var canonicalSymbol = Symbol.Create(Futures.Indices.VIX, SecurityType.Future, Market.CBOE, "/VX"); var quoteCurrency = new Cash(Currencies.USD, 0, 1); var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(Market.CBOE, canonicalSymbol, SecurityType.Future); var config = new SubscriptionDataConfig( typeof(ZipEntryName), canonicalSymbol, Resolution.Minute, TimeZones.Utc, TimeZones.Chicago, true, false, false, false, TickType.Quote, false, DataNormalizationMode.Raw ); var future = new Future( canonicalSymbol, exchangeHours, quoteCurrency, SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var universeSettings = new UniverseSettings(Resolution.Minute, 0, true, false, TimeSpan.Zero); var universe = new FuturesChainUniverse(future, universeSettings); var request = new SubscriptionRequest(true, universe, future, config, startTime, Time.EndOfTime); var enumerator = factory.CreateEnumerator(request, new DefaultDataProvider()); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); var data = enumerator.Current as FuturesChainUniverseDataCollection; Assert.IsNotNull(data); Assert.AreEqual(1, data.Data.Count); timeProvider.Advance(Time.OneSecond); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); timeProvider.Advance(Time.OneMinute); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); timeProvider.Advance(Time.OneDay); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(2, symbolUniverse.TotalLookupCalls); data = enumerator.Current as FuturesChainUniverseDataCollection; Assert.IsNotNull(data); Assert.AreEqual(2, data.Data.Count); timeProvider.Advance(Time.OneMinute); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNull(enumerator.Current); Assert.AreEqual(2, symbolUniverse.TotalLookupCalls); enumerator.Dispose(); }
public void OpenExchanges_DoIndicateRealTimePriceUpdates() { var security = new Security(Symbol.Empty, _exchangeHours, new Cash("USA", 100m, 1m), SymbolProperties.GetDefault("USA")); var subscription = new Subscription(null, security, null, null, new TimeZoneOffsetProviderAlwaysOpen(), DateTime.MinValue, DateTime.MaxValue, false); Assert.IsTrue(_liveTradingDataFeed.UpdateRealTimePrice(subscription, new TimeZoneOffsetProviderAlwaysOpen())); }
public void SellOnThursdaySettleOnTuesday() { var securities = new SecurityManager(TimeKeeper); var transactions = new SecurityTransactionManager(null, securities); var portfolio = new SecurityPortfolioManager(securities, transactions); // settlement at T+3, 8:00 AM var model = new DelayedSettlementModel(3, TimeSpan.FromHours(8)); var config = CreateTradeBarConfig(Symbols.SPY); var security = new Security( SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(), config, new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); portfolio.SetCash(3000); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(0, portfolio.UnsettledCash); // Sell on Thursday var timeUtc = Noon.AddDays(3).ConvertToUtc(TimeZones.NewYork); model.ApplyFunds(portfolio, security, timeUtc, Currencies.USD, 1000); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Friday, still unsettled timeUtc = timeUtc.AddDays(1); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Saturday, still unsettled timeUtc = timeUtc.AddDays(1); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Sunday, still unsettled timeUtc = timeUtc.AddDays(1); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Monday, still unsettled timeUtc = timeUtc.AddDays(1); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Tuesday at 7:55 AM, still unsettled timeUtc = timeUtc.AddDays(1).AddHours(-4).AddMinutes(-5); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(3000, portfolio.Cash); Assert.AreEqual(1000, portfolio.UnsettledCash); // Tuesday at 8 AM, now settled timeUtc = timeUtc.AddMinutes(5); portfolio.ScanForCashSettlement(timeUtc); Assert.AreEqual(4000, portfolio.Cash); Assert.AreEqual(0, portfolio.UnsettledCash); }
/// <summary> /// Creates a subscription to process the history request /// </summary> private static Subscription CreateSubscription(HistoryRequest request, IEnumerable <BaseData> history) { // data reader expects these values in local times var start = request.StartTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var end = request.EndTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.TimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, null, true, request.DataNormalizationMode ); var security = new Security(request.ExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)); var reader = history.GetEnumerator(); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, security.IsExtendedMarketHours, end, config.Increment); } var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, start, end); return(new Subscription(null, security, config, reader, timeZoneOffsetProvider, start, end, false)); }
/// <summary> /// Creates a subscription to process the request /// </summary> private Subscription CreateSubscription(HistoryRequest request, DateTime start, DateTime end) { // data reader expects these values in local times start = start.ConvertFromUtc(request.ExchangeHours.TimeZone); end = end.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance ); var mapFileResolver = config.SecurityType == SecurityType.Equity ? _mapFileProvider.Get(config.Market) : MapFileResolver.Empty; if (config.SecurityType == SecurityType.Equity) { var mapFile = mapFileResolver.ResolveMapFile(config.Symbol.ID.Symbol, config.Symbol.ID.Date); config.MappedSymbol = mapFile.GetMappedSymbol(start, config.MappedSymbol); } var dataReader = new SubscriptionDataReader(config, start, end, mapFileResolver, _factorFileProvider, Time.EachTradeableDay(request.ExchangeHours, start, end), false, _dataCacheProvider ); dataReader.InvalidConfigurationDetected += (sender, args) => { OnInvalidConfigurationDetected(new InvalidConfigurationDetectedEventArgs(args.Message)); }; dataReader.NumericalPrecisionLimited += (sender, args) => { OnNumericalPrecisionLimited(new NumericalPrecisionLimitedEventArgs(args.Message)); }; dataReader.DownloadFailed += (sender, args) => { OnDownloadFailed(new DownloadFailedEventArgs(args.Message, args.StackTrace)); }; dataReader.ReaderErrorDetected += (sender, args) => { OnReaderErrorDetected(new ReaderErrorDetectedEventArgs(args.Message, args.StackTrace)); }; var enumerator = CorporateEventEnumeratorFactory.CreateEnumerators( config, _factorFileProvider, dataReader, mapFileResolver, false); IEnumerator <BaseData> reader = new SynchronizingEnumerator(dataReader, enumerator); // has to be initialized after adding all the enumerators since it will execute a MoveNext dataReader.Initialize(); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, security.IsExtendedMarketHours, end, config.Increment, config.DataTimeZone); } // since the SubscriptionDataReader performs an any overlap condition on the trade bar's entire // range (time->end time) we can end up passing the incorrect data (too far past, possibly future), // so to combat this we deliberately filter the results from the data reader to fix these cases // which only apply to non-tick data reader = new SubscriptionFilterEnumerator(reader, security, end); reader = new FilterEnumerator <BaseData>(reader, data => { // allow all ticks if (config.Resolution == Resolution.Tick) { return(true); } // filter out future data if (data.EndTime > end) { return(false); } // filter out data before the start return(data.EndTime > start); }); var timeZoneOffsetProvider = new TimeZoneOffsetProvider(security.Exchange.TimeZone, start, end); var subscriptionDataEnumerator = SubscriptionData.Enumerator(config, security, timeZoneOffsetProvider, reader); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, start, end); return(new Subscription(subscriptionRequest, subscriptionDataEnumerator, timeZoneOffsetProvider)); }
public void EnsureCurrencyDataFeedChecksSecurityChangesForSecurity() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cash = new Cash("JPY", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("JPY", cash); var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var abcConfig = subscriptions.Add(Symbols.SPY, Resolution.Minute, TimeZone, TimeZone); var securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.SPY, new Security( SecurityExchangeHours, abcConfig, new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); var usdjpy = new Security(Symbols.USDJPY, SecurityExchangeHours, new Cash("JPY", 0, 0), SymbolProperties.GetDefault("JPY"), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache()); var changes = new SecurityChanges(new[] { usdjpy }, Enumerable.Empty <Security>()); var addedSecurities = cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, changes, dataManager.SecurityService, cashBook.AccountCurrency); // the security exists in SecurityChanges so it is NOT added to the security manager or subscriptions // this security will be added by the algorithm manager Assert.True(addedSecurities == null || addedSecurities.Count == 0); }
public void TestBasicFeaturesWithOptionsFutures() { var securities = new SecurityManager(TimeKeeper); var marketHoursDatabase = MarketHoursDatabase.FromDataFolder(); securities.Add( Symbols.SPY, new Security( SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Equity, Symbols.SPY), new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); securities[Symbols.SPY].SetMarketPrice(new TradeBar { Time = securities.UtcTime, Symbol = Symbols.SPY, Close = 195 }); var option1 = Symbol.CreateOption("SPY", Market.USA, OptionStyle.American, OptionRight.Call, 192m, new DateTime(2016, 02, 16)); securities.Add( option1, new Option( SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Option, option1), new Cash(Currencies.USD, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ) ); var option2 = Symbol.CreateOption("SPY", Market.USA, OptionStyle.American, OptionRight.Call, 193m, new DateTime(2016, 03, 19)); securities.Add( option2, new Option( SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Option, option2), new Cash(Currencies.USD, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ) ); var future1 = Symbol.CreateFuture(QuantConnect.Securities.Futures.Indices.SP500EMini, Market.CME, new DateTime(2016, 02, 16)); securities.Add( future1, new Future( SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Future, future1), new Cash(Currencies.USD, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ) ); var future2 = Symbol.CreateFuture(QuantConnect.Securities.Futures.Indices.SP500EMini, Market.CME, new DateTime(2016, 02, 19)); securities.Add( future2, new Future( SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Future, future2), new Cash(Currencies.USD, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ) ); var cal = new TradingCalendar(securities, marketHoursDatabase); var optionDays = cal.GetDaysByType(TradingDayType.OptionExpiration, new DateTime(2016, 02, 16), new DateTime(2016, 03, 19)).Count(); Assert.AreEqual(2, optionDays); var futureDays = cal.GetDaysByType(TradingDayType.OptionExpiration, new DateTime(2016, 02, 16), new DateTime(2016, 03, 19)).Count(); Assert.AreEqual(2, futureDays); var days = cal.GetTradingDays(new DateTime(2016, 02, 16), new DateTime(2016, 03, 19)); var optionAndfutureDays = days.Where(x => x.FutureExpirations.Any() || x.OptionExpirations.Any()).Count(); Assert.AreEqual(3, optionAndfutureDays); // why? because option1 and future1 expire in one day 2016-02-16. Lets have a look. var day = cal.GetTradingDay(new DateTime(2016, 02, 16)); Assert.AreEqual(1, day.OptionExpirations.Count()); Assert.AreEqual(1, day.FutureExpirations.Count()); var businessDays = days.Where(x => x.BusinessDay).Count(); Assert.AreEqual(24, businessDays); var weekends = days.Where(x => x.Weekend).Count(); Assert.AreEqual(9, weekends); Assert.AreEqual(24 + 9, (new DateTime(2016, 03, 19) - new DateTime(2016, 02, 16)).TotalDays + 1 /*inclusive*/); }
public void InitializeBrokerage() { InteractiveBrokersGatewayRunner.Start(Config.Get("ib-controller-dir"), Config.Get("ib-tws-dir"), Config.Get("ib-user-name"), Config.Get("ib-password"), Config.Get("ib-trading-mode"), Config.GetBool("ib-use-tws") ); // grabs account info from configuration var securityProvider = new SecurityProvider(); securityProvider[Symbols.USDJPY] = new Security(SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork), new SubscriptionDataConfig(typeof(TradeBar), Symbols.USDJPY, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, false, false, false), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)); _interactiveBrokersBrokerage = new InteractiveBrokersBrokerage(new OrderProvider(_orders), securityProvider); _interactiveBrokersBrokerage.Connect(); }
public void RefreshesOptionChainUniverseOnDateChange() { var startTime = new DateTime(2018, 10, 19, 10, 0, 0); var timeProvider = new ManualTimeProvider(startTime); var canonicalSymbol = Symbol.Create("SPY", SecurityType.Option, Market.USA, "?SPY"); var quoteCurrency = new Cash(Currencies.USD, 0, 1); var exchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(Market.USA, canonicalSymbol, SecurityType.Option); var config = new SubscriptionDataConfig( typeof(ZipEntryName), canonicalSymbol, Resolution.Minute, TimeZones.Utc, TimeZones.NewYork, true, false, false, false, TickType.Quote, false, DataNormalizationMode.Raw ); var option = new Option( canonicalSymbol, exchangeHours, quoteCurrency, new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var fillForwardResolution = Ref.CreateReadOnly(() => Resolution.Minute.ToTimeSpan()); var symbolUniverse = new TestDataQueueUniverseProvider(timeProvider); TradeBarBuilderEnumerator underlyingEnumerator = null; Func <SubscriptionRequest, IEnumerator <BaseData>, IEnumerator <BaseData> > underlyingEnumeratorFunc = (req, input) => { underlyingEnumerator = (TradeBarBuilderEnumerator)input; return(new LiveFillForwardEnumerator( timeProvider, input, option.Exchange, fillForwardResolution, false, Time.EndOfTime, Resolution.Minute.ToTimeSpan(), TimeZones.Utc, Time.BeginningOfTime)); }; var factory = new OptionChainUniverseSubscriptionEnumeratorFactory(underlyingEnumeratorFunc, symbolUniverse, timeProvider); var universeSettings = new UniverseSettings(Resolution.Minute, 0, true, false, TimeSpan.Zero); var universe = new OptionChainUniverse(option, universeSettings, true); var request = new SubscriptionRequest(true, universe, option, config, startTime, Time.EndOfTime); var enumerator = (DataQueueOptionChainUniverseDataCollectionEnumerator)factory.CreateEnumerator(request, new DefaultDataProvider()); // 2018-10-19 10:00 AM UTC underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); // no underlying data available yet Assert.IsNull(enumerator.Current); Assert.AreEqual(0, symbolUniverse.TotalLookupCalls); // 2018-10-19 10:01 AM UTC timeProvider.Advance(Time.OneMinute); underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); var data = enumerator.Current; Assert.IsNotNull(data); Assert.AreEqual(1, data.Data.Count); Assert.IsNotNull(data.Underlying); // 2018-10-19 10:02 AM UTC timeProvider.Advance(Time.OneMinute); underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); data = enumerator.Current; Assert.IsNotNull(data); Assert.AreEqual(1, data.Data.Count); Assert.IsNotNull(data.Underlying); // 2018-10-19 10:03 AM UTC timeProvider.Advance(Time.OneMinute); underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(1, symbolUniverse.TotalLookupCalls); data = enumerator.Current; Assert.IsNotNull(data); Assert.AreEqual(1, data.Data.Count); Assert.IsNotNull(data.Underlying); // 2018-10-20 10:03 AM UTC timeProvider.Advance(Time.OneDay); underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(2, symbolUniverse.TotalLookupCalls); data = enumerator.Current; Assert.IsNotNull(data); Assert.AreEqual(2, data.Data.Count); Assert.IsNotNull(data.Underlying); // 2018-10-20 10:04 AM UTC timeProvider.Advance(Time.OneMinute); underlyingEnumerator.ProcessData(new Tick { Symbol = Symbols.SPY, Value = 280m }); Assert.IsTrue(enumerator.MoveNext()); Assert.IsNotNull(enumerator.Current); Assert.AreEqual(2, symbolUniverse.TotalLookupCalls); data = enumerator.Current; Assert.IsNotNull(data); Assert.AreEqual(2, data.Data.Count); Assert.IsNotNull(data.Underlying); enumerator.Dispose(); }
private static TestCaseData[] GetValueTestParameters() { const decimal delta = 1m; const decimal price = 1.2345m; const int quantity = 100; const decimal pricePlusDelta = price + delta; const decimal priceMinusDelta = price - delta; var tz = TimeZones.NewYork; var time = new DateTime(2016, 2, 4, 16, 0, 0).ConvertToUtc(tz); var equity = new Equity( SecurityExchangeHours.AlwaysOpen(tz), new SubscriptionDataConfig(typeof(TradeBar), Symbols.SPY, Resolution.Minute, tz, tz, true, false, false), new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); equity.SetMarketPrice(new Tick { Value = price }); var gbpCash = new Cash("GBP", 0, 1.46m); var properties = SymbolProperties.GetDefault(gbpCash.Symbol); var forex = new Forex( SecurityExchangeHours.AlwaysOpen(tz), gbpCash, new SubscriptionDataConfig(typeof(TradeBar), Symbols.EURGBP, Resolution.Minute, tz, tz, true, false, false), properties, ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); forex.SetMarketPrice(new Tick { Value = price }); var eurCash = new Cash("EUR", 0, 1.12m); properties = new SymbolProperties("Euro-Bund", eurCash.Symbol, 10, 0.1m, 1); var cfd = new Cfd( SecurityExchangeHours.AlwaysOpen(tz), eurCash, new SubscriptionDataConfig(typeof(TradeBar), Symbols.DE10YBEUR, Resolution.Minute, tz, tz, true, false, false), properties, ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); cfd.SetMarketPrice(new Tick { Value = price }); var multiplierTimesConversionRate = properties.ContractMultiplier * eurCash.ConversionRate; var option = new Option( SecurityExchangeHours.AlwaysOpen(tz), new SubscriptionDataConfig( typeof(TradeBar), Symbols.SPY_P_192_Feb19_2016, Resolution.Minute, tz, tz, true, false, false ), new Cash(Currencies.USD, 0, 1m), new OptionSymbolProperties(SymbolProperties.GetDefault(Currencies.USD)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); option.SetMarketPrice(new Tick { Value = price }); return(new List <ValueTestParameters> { // equity orders new ValueTestParameters("EquityLongMarketOrder", equity, new MarketOrder(Symbols.SPY, quantity, time), quantity * price), new ValueTestParameters("EquityShortMarketOrder", equity, new MarketOrder(Symbols.SPY, -quantity, time), -quantity * price), new ValueTestParameters("EquityLongLimitOrder", equity, new LimitOrder(Symbols.SPY, quantity, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("EquityShortLimit Order", equity, new LimitOrder(Symbols.SPY, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("EquityLongStopLimitOrder", equity, new StopLimitOrder(Symbols.SPY, quantity, .5m * priceMinusDelta, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("EquityShortStopLimitOrder", equity, new StopLimitOrder(Symbols.SPY, -quantity, 1.5m * pricePlusDelta, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("EquityLongStopMarketOrder", equity, new StopMarketOrder(Symbols.SPY, quantity, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("EquityLongStopMarketOrder", equity, new StopMarketOrder(Symbols.SPY, quantity, pricePlusDelta, time), quantity * price), new ValueTestParameters("EquityShortStopMarketOrder", equity, new StopMarketOrder(Symbols.SPY, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("EquityShortStopMarketOrder", equity, new StopMarketOrder(Symbols.SPY, -quantity, priceMinusDelta, time), -quantity * price), // forex orders new ValueTestParameters("ForexLongMarketOrder", forex, new MarketOrder(Symbols.EURGBP, quantity, time), quantity * price * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexShortMarketOrder", forex, new MarketOrder(Symbols.EURGBP, -quantity, time), -quantity * price * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexLongLimitOrder", forex, new LimitOrder(Symbols.EURGBP, quantity, priceMinusDelta, time), quantity * priceMinusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexShortLimit Order", forex, new LimitOrder(Symbols.EURGBP, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexLongStopLimitOrder", forex, new StopLimitOrder(Symbols.EURGBP, quantity, .5m * priceMinusDelta, priceMinusDelta, time), quantity * priceMinusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexShortStopLimitOrder", forex, new StopLimitOrder(Symbols.EURGBP, -quantity, 1.5m * pricePlusDelta, pricePlusDelta, time), -quantity * pricePlusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexLongStopMarketOrder", forex, new StopMarketOrder(Symbols.EURGBP, quantity, priceMinusDelta, time), quantity * priceMinusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexLongStopMarketOrder", forex, new StopMarketOrder(Symbols.EURGBP, quantity, pricePlusDelta, time), quantity * price * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexShortStopMarketOrder", forex, new StopMarketOrder(Symbols.EURGBP, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta * forex.QuoteCurrency.ConversionRate), new ValueTestParameters("ForexShortStopMarketOrder", forex, new StopMarketOrder(Symbols.EURGBP, -quantity, priceMinusDelta, time), -quantity * price * forex.QuoteCurrency.ConversionRate), // cfd orders new ValueTestParameters("CfdLongMarketOrder", cfd, new MarketOrder(Symbols.DE10YBEUR, quantity, time), quantity * price * multiplierTimesConversionRate), new ValueTestParameters("CfdShortMarketOrder", cfd, new MarketOrder(Symbols.DE10YBEUR, -quantity, time), -quantity * price * multiplierTimesConversionRate), new ValueTestParameters("CfdLongLimitOrder", cfd, new LimitOrder(Symbols.DE10YBEUR, quantity, priceMinusDelta, time), quantity * priceMinusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdShortLimit Order", cfd, new LimitOrder(Symbols.DE10YBEUR, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdLongStopLimitOrder", cfd, new StopLimitOrder(Symbols.DE10YBEUR, quantity, .5m * priceMinusDelta, priceMinusDelta, time), quantity * priceMinusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdShortStopLimitOrder", cfd, new StopLimitOrder(Symbols.DE10YBEUR, -quantity, 1.5m * pricePlusDelta, pricePlusDelta, time), -quantity * pricePlusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdLongStopMarketOrder", cfd, new StopMarketOrder(Symbols.DE10YBEUR, quantity, priceMinusDelta, time), quantity * priceMinusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdLongStopMarketOrder", cfd, new StopMarketOrder(Symbols.DE10YBEUR, quantity, pricePlusDelta, time), quantity * price * multiplierTimesConversionRate), new ValueTestParameters("CfdShortStopMarketOrder", cfd, new StopMarketOrder(Symbols.DE10YBEUR, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta * multiplierTimesConversionRate), new ValueTestParameters("CfdShortStopMarketOrder", cfd, new StopMarketOrder(Symbols.DE10YBEUR, -quantity, priceMinusDelta, time), -quantity * price * multiplierTimesConversionRate), // equity/index option orders new ValueTestParameters("OptionLongMarketOrder", option, new MarketOrder(Symbols.SPY_P_192_Feb19_2016, quantity, time), quantity * price), new ValueTestParameters("OptionShortMarketOrder", option, new MarketOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, time), -quantity * price), new ValueTestParameters("OptionLongLimitOrder", option, new LimitOrder(Symbols.SPY_P_192_Feb19_2016, quantity, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("OptionShortLimit Order", option, new LimitOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("OptionLongStopLimitOrder", option, new StopLimitOrder(Symbols.SPY_P_192_Feb19_2016, quantity, .5m * priceMinusDelta, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("OptionShortStopLimitOrder", option, new StopLimitOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, 1.5m * pricePlusDelta, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("OptionLongStopMarketOrder", option, new StopMarketOrder(Symbols.SPY_P_192_Feb19_2016, quantity, priceMinusDelta, time), quantity * priceMinusDelta), new ValueTestParameters("OptionLongStopMarketOrder", option, new StopMarketOrder(Symbols.SPY_P_192_Feb19_2016, quantity, pricePlusDelta, time), quantity * price), new ValueTestParameters("OptionShortStopMarketOrder", option, new StopMarketOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, pricePlusDelta, time), -quantity * pricePlusDelta), new ValueTestParameters("OptionShortStopMarketOrder", option, new StopMarketOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, priceMinusDelta, time), -quantity * price), new ValueTestParameters("OptionExerciseOrderPut", option, new OptionExerciseOrder(Symbols.SPY_P_192_Feb19_2016, quantity, time), quantity * option.Symbol.ID.StrikePrice), new ValueTestParameters("OptionAssignmentOrderPut", option, new OptionExerciseOrder(Symbols.SPY_P_192_Feb19_2016, -quantity, time), -quantity * option.Symbol.ID.StrikePrice), new ValueTestParameters("OptionExerciseOrderCall", option, new OptionExerciseOrder(Symbols.SPY_C_192_Feb19_2016, quantity, time), quantity * option.Symbol.ID.StrikePrice), new ValueTestParameters("OptionAssignmentOrderCall", option, new OptionExerciseOrder(Symbols.SPY_C_192_Feb19_2016, -quantity, time), -quantity * option.Symbol.ID.StrikePrice), }.Select(x => new TestCaseData(x).SetName(x.Name)).ToArray()); }
public void GtdTimeInForceCryptoOrderExpiresAtMidnightUtcAfterExpiryDate() { var utcTime = new DateTime(2018, 4, 27, 10, 0, 0); var security = new Crypto( SecurityExchangeHours.AlwaysOpen(TimeZones.Utc), new Cash(Currencies.USD, 0, 1m), new SubscriptionDataConfig( typeof(QuoteBar), Symbols.BTCUSD, Resolution.Minute, TimeZones.Utc, TimeZones.Utc, true, true, true ), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); var localTimeKeeper = new LocalTimeKeeper(utcTime, TimeZones.Utc); security.SetLocalTimeKeeper(localTimeKeeper); var timeInForce = TimeInForce.GoodTilDate(new DateTime(2018, 5, 1)); var orderProperties = new OrderProperties { TimeInForce = timeInForce }; var order = new LimitOrder(Symbols.BTCUSD, 10, 100, utcTime, "", orderProperties); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); var fill1 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.PartiallyFilled, OrderDirection.Buy, order.LimitPrice, 3, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); var fill2 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.Filled, OrderDirection.Buy, order.LimitPrice, 7, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); // April 27th before midnight localTimeKeeper.UpdateTime(utcTime.AddHours(14).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // April 28th at midnight localTimeKeeper.UpdateTime(utcTime.AddHours(14)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st at 10 AM localTimeKeeper.UpdateTime(utcTime.AddDays(4)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st before midnight localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(14).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 2nd at midnight localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(14)); Assert.IsTrue(timeInForce.IsOrderExpired(security, order)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); }
public void GtdTimeInForceEquityOrderExpiresAtMarketCloseOnExpiryDate() { var utcTime = new DateTime(2018, 4, 27, 10, 0, 0).ConvertToUtc(TimeZones.NewYork); var security = new Equity( SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours(), new SubscriptionDataConfig( typeof(TradeBar), Symbols.SPY, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, true, true, true ), new Cash(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); var localTimeKeeper = new LocalTimeKeeper(utcTime, TimeZones.NewYork); security.SetLocalTimeKeeper(localTimeKeeper); var timeInForce = TimeInForce.GoodTilDate(new DateTime(2018, 5, 1)); var orderProperties = new OrderProperties { TimeInForce = timeInForce }; var order = new LimitOrder(Symbols.SPY, 10, 100, utcTime, "", orderProperties); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); var fill1 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.PartiallyFilled, OrderDirection.Buy, order.LimitPrice, 3, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); var fill2 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.Filled, OrderDirection.Buy, order.LimitPrice, 7, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); // April 27th before market close localTimeKeeper.UpdateTime(utcTime.AddHours(6).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // April 27th at market close localTimeKeeper.UpdateTime(utcTime.AddHours(6)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st at 10 AM localTimeKeeper.UpdateTime(utcTime.AddDays(4)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st before market close localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(6).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st at market close localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(6)); Assert.IsTrue(timeInForce.IsOrderExpired(security, order)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); }
private static DateRules GetDateRules() { var timeKeeper = new TimeKeeper(DateTime.Today, new List <DateTimeZone>()); var manager = new SecurityManager(timeKeeper); var securityExchangeHours = MarketHoursDatabase.FromDataFolder().GetExchangeHours(Market.USA, null, SecurityType.Equity); var config = new SubscriptionDataConfig(typeof(TradeBar), Symbols.SPY, Resolution.Daily, TimeZones.NewYork, TimeZones.NewYork, true, false, false); manager.Add(Symbols.SPY, new Security(securityExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); var rules = new DateRules(manager); return(rules); }
public SymbolViewModel(SymbolProperties model, int imageSize) { _model = model; _imageSize = imageSize; }
public void GtdTimeInForceForexOrderBeforeExpiresAt5PMOnExpiryDate() { // set time to 10:00:00 AM (NY time) var utcTime = new DateTime(2018, 4, 27, 10, 0, 0).ConvertToUtc(TimeZones.NewYork); var security = new Forex( SecurityExchangeHoursTests.CreateForexSecurityExchangeHours(), new Cash(Currencies.USD, 0, 1m), new SubscriptionDataConfig( typeof(QuoteBar), Symbols.EURUSD, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, true, true, true ), SymbolProperties.GetDefault(Currencies.USD), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ); var localTimeKeeper = new LocalTimeKeeper(utcTime, TimeZones.NewYork); security.SetLocalTimeKeeper(localTimeKeeper); var timeInForce = TimeInForce.GoodTilDate(new DateTime(2018, 5, 1)); var orderProperties = new OrderProperties { TimeInForce = timeInForce }; var order = new LimitOrder(Symbols.EURUSD, 10, 100, utcTime, "", orderProperties); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); var fill1 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.PartiallyFilled, OrderDirection.Buy, order.LimitPrice, 3, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); var fill2 = new OrderEvent(order.Id, order.Symbol, utcTime, OrderStatus.Filled, OrderDirection.Buy, order.LimitPrice, 7, OrderFee.Zero); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); // April 27th 4:59:59 PM (NY time) localTimeKeeper.UpdateTime(utcTime.AddHours(7).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // April 27th 5:00:00 PM (NY time) localTimeKeeper.UpdateTime(utcTime.AddHours(7)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st at 10 AM localTimeKeeper.UpdateTime(utcTime.AddDays(4)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st 4:59:59 PM (NY time) localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(7).AddSeconds(-1)); Assert.IsFalse(timeInForce.IsOrderExpired(security, order)); // May 1st 5:00:00 PM (NY time) localTimeKeeper.UpdateTime(utcTime.AddDays(4).AddHours(7)); Assert.IsTrue(timeInForce.IsOrderExpired(security, order)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill1)); Assert.IsTrue(timeInForce.IsFillValid(security, order, fill2)); }