/// <summary> /// Initializes a new instance of the <see cref="SubscriptionSynchronizer"/> class /// </summary> /// <param name="universeSelection">The universe selection instance used to handle universe /// selection subscription output</param> /// <param name="sliceTimeZone">The time zone of the created slice object</param> /// <param name="cashBook">The cash book, used for creating the cash book updates</param> /// <returns>A time slice for the specified frontier time</returns> /// <param name="frontierUtc">The initial UTC frontier time to syncronize at</param> public SubscriptionSynchronizer(UniverseSelection universeSelection, DateTimeZone sliceTimeZone, CashBook cashBook, DateTime frontierUtc) { _frontier = frontierUtc; _universeSelection = universeSelection; _sliceTimeZone = sliceTimeZone; _cashBook = cashBook; }
public void EnsureCurrencyDataFeedForCryptoCurrency() { var book = new CashBook { { "USD", new Cash("USD", 100, 1) }, { "BTC", new Cash("BTC", 100, 6000) }, { "LTC", new Cash("LTC", 100, 55) }, { "ETH", new Cash("ETH", 100, 290) }, { "EUR", new Cash("EUR", 100, 1.2m) }, { "JPY", new Cash("JPY", 100, 0.0088m) }, { "XAG", new Cash("XAG", 100, 1275) }, { "XAU", new Cash("XAU", 100, 17) } }; var subscriptions = new SubscriptionManager(AlgorithmSettings, TimeKeeper); var securities = new SecurityManager(TimeKeeper); book.EnsureCurrencyDataFeeds(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap); var symbols = subscriptions.Subscriptions.Select(sdc => sdc.Symbol).ToHashSet(); Assert.IsTrue(symbols.Contains(Symbols.BTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.LTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.ETHUSD)); Assert.IsTrue(symbols.Contains(Symbols.EURUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAGUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAUUSD)); }
public EditPayment(CashBook frm1) { owner = frm1; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AddPayment_FormClosing); InitializeComponent(); }
public void EnsureInternalCurrencyDataFeedsForNonUsdQuoteCurrencyGetAdded() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cashJPY = new Cash("JPY", quantity, conversionRate); var cashGBP = new Cash("GBP", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("JPY", cashJPY); cashBook.Add("GBP", cashGBP); var symbol = Symbol.Create("GBPJPY", SecurityType.Forex, Market.FXCM); var subscriptions = new SubscriptionManager(TimeKeeper, new DataManagerStub()); var securities = new SecurityManager(TimeKeeper); securities.Add(symbol, new Security(SecurityExchangeHours, subscriptions.Add(symbol, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); cashJPY.EnsureCurrencyDataFeed(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook, SecurityChanges.None); var config1 = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.USDJPY); Assert.IsTrue(config1.IsInternalFeed); cashGBP.EnsureCurrencyDataFeed(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook, SecurityChanges.None); var config2 = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.GBPUSD); Assert.IsTrue(config2.IsInternalFeed); }
public void EnsureCurrencyDataFeedForCryptoCurrency() { var book = new CashBook { { "USD", new Cash("USD", 100, 1) }, { "BTC", new Cash("BTC", 100, 6000) }, { "LTC", new Cash("LTC", 100, 55) }, { "ETH", new Cash("ETH", 100, 290) }, { "EUR", new Cash("EUR", 100, 1.2m) }, { "JPY", new Cash("JPY", 100, 0.0088m) }, { "XAG", new Cash("XAG", 100, 1275) }, { "XAU", new Cash("XAU", 100, 17) } }; var subscriptions = new SubscriptionManager(TimeKeeper, new DataManagerStub()); var securities = new SecurityManager(TimeKeeper); book.EnsureCurrencyDataFeeds(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, SecurityChanges.None); var symbols = subscriptions.Subscriptions.Select(sdc => sdc.Symbol).ToHashSet(); Assert.IsTrue(symbols.Contains(Symbols.BTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.LTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.ETHUSD)); Assert.IsTrue(symbols.Contains(Symbols.EURUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAGUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAUUSD)); foreach (var subscription in subscriptions.Subscriptions) { Assert.AreEqual( subscription.Symbol.SecurityType == SecurityType.Crypto ? TickType.Trade : TickType.Quote, subscription.TickType); } }
public void EnsureCurrencyDataFeedMarksIsCurrencyDataFeedForNewSubscriptions() { 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 securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.EURUSD, new Security( SecurityExchangeHours, subscriptions.Add(Symbols.EURUSD, Resolution.Minute, TimeZone, TimeZone), new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, cashBook.AccountCurrency); var config = subscriptions.SubscriptionDataConfigService.GetSubscriptionDataConfigs(Symbols.USDJPY, includeInternalConfigs: true).Single(); Assert.IsTrue(config.IsInternalFeed); }
public void EnsureCurrencyDataFeedAddsSubscription() { 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(Currencies.USD, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), cashBook, RegisteredSecurityDataTypesProvider.Null, new SecurityCache())); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, cashBook.AccountCurrency); Assert.AreEqual(1, subscriptions.SubscriptionDataConfigService.GetSubscriptionDataConfigs(Symbols.USDJPY, includeInternalConfigs: true).Count); Assert.AreEqual(1, securities.Values.Count(x => x.Symbol == Symbols.USDJPY)); }
public void EnsureCurrencyDataFeedDoesNotMarkIsCurrencyDataFeedForExistantSubscriptions() { 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(); subscriptions.SetDataManager(new DataManagerStub(TimeKeeper)); var securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.USDJPY, new Security( SecurityExchangeHours, subscriptions.Add(Symbols.USDJPY, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency), ErrorCurrencyConverter.Instance ) ); cash.EnsureCurrencyDataFeed(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook, SecurityChanges.None); var config = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.USDJPY); Assert.IsFalse(config.IsInternalFeed); }
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(); subscriptions.SetDataManager(new DataManagerStub(TimeKeeper)); 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 ) ); var usdjpy = new Security(Symbols.USDJPY, SecurityExchangeHours, new Cash("JPY", 0, 0), SymbolProperties.GetDefault("JPY"), ErrorCurrencyConverter.Instance); var changes = new SecurityChanges(new[] { usdjpy }, Enumerable.Empty <Security>()); var addedSecurity = cash.EnsureCurrencyDataFeed(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook, changes); // 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.IsNull(addedSecurity); }
public void UpdateEventNotCalledForCashUpdatesAfterSteppedOn() { var cashBook = new CashBook(); var called = false; var updatedCalled = false; var cash = new Cash(Currencies.USD, 1, 1); var cash2 = new Cash(Currencies.USD, 1, 1); cashBook.Add(cash.Symbol, cash); cashBook.Add(cash.Symbol, cash2); cashBook.Updated += (sender, updateType) => { called = true; updatedCalled = updateType == CashBook.UpdateType.Updated; }; cash.Update(new Tick { Value = 10 }); Assert.IsFalse(called); cash2.Update(new Tick { Value = 10 }); Assert.IsTrue(updatedCalled); }
public void UpdateModifiesConversionRateAsInvertedValue() { 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(); subscriptions.SetDataManager(new DataManagerStub(TimeKeeper)); var securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.USDJPY, new Security( SecurityExchangeHours, subscriptions.Add(Symbols.USDJPY, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency), ErrorCurrencyConverter.Instance ) ); // we need to get subscription index cash.EnsureCurrencyDataFeed(securities, subscriptions, AlwaysOpenMarketHoursDatabase, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook, SecurityChanges.None); var last = 120m; cash.Update(new Tick(DateTime.Now, Symbols.USDJPY, last, 119.95m, 120.05m)); // jpy is inverted, so compare on the inverse Assert.AreEqual(1 / last, cash.ConversionRate); }
public void WillThrowIfGetNullCurrency() { Assert.Throws <InvalidOperationException>(() => { var symbol = new CashBook()[Currencies.NullCurrency].Symbol; }); }
public void WontAddNullCurrencyCash() { var book = new CashBook { { Currencies.NullCurrency, 1, 1 } }; Assert.AreEqual(1, book.Count); var cash = book.Single().Value; Assert.AreEqual(Currencies.USD, cash.Symbol); book.Add(Currencies.NullCurrency, 1, 1); Assert.AreEqual(1, book.Count); cash = book.Single().Value; Assert.AreEqual(Currencies.USD, cash.Symbol); book.Add(Currencies.NullCurrency, new Cash(Currencies.NullCurrency, 1, 1)); Assert.AreEqual(1, book.Count); cash = book.Single().Value; Assert.AreEqual(Currencies.USD, cash.Symbol); book[Currencies.NullCurrency] = new Cash(Currencies.NullCurrency, 1, 1); Assert.AreEqual(1, book.Count); cash = book.Single().Value; Assert.AreEqual(Currencies.USD, cash.Symbol); }
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 = SecurityChangesTests.CreateNonInternal(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); }
/// <summary> /// Initializes a new instance of the <see cref="SubscriptionSynchronizer"/> class /// </summary> /// <param name="universeSelection">The universe selection instance used to handle universe /// selection subscription output</param> /// <param name="sliceTimeZone">The time zone of the created slice object</param> /// <param name="cashBook">The cash book, used for creating the cash book updates</param> /// <returns>A time slice for the specified frontier time</returns> /// <param name="timeProvider">The time provider, used to obtain the current frontier UTC value.</param> public SubscriptionSynchronizer(UniverseSelection universeSelection, DateTimeZone sliceTimeZone, CashBook cashBook, ITimeProvider timeProvider) { _timeProvider = timeProvider; _universeSelection = universeSelection; _sliceTimeZone = sliceTimeZone; _cashBook = cashBook; }
public CashBook FindCashBook(string code) { var queryResult = Query(new GetCashBook { Code = code }); return(CashBook.FromQueryResult(code, queryResult)); }
public void ConvertsToAccountCurrencyProperly() { var book = new CashBook(); book.Add("EUR", 0, 1.10m); var expected = 1100m; var actual = book.ConvertToAccountCurrency(1000, "EUR"); Assert.AreEqual(expected, actual); }
public void InitializesWithAccountCurrencyAdded() { var book = new CashBook(); Assert.AreEqual(1, book.Count); var cash = book.Single().Value; Assert.AreEqual(CashBook.AccountCurrency, cash.Symbol); Assert.AreEqual(0, cash.Amount); Assert.AreEqual(1m, cash.ConversionRate); }
private void metroTile1_Click(object sender, EventArgs e) { CashBook obj2 = new CashBook(); this.Close(); AddReciept obj = new AddReciept(obj2); obj.Show(); }
public void SendFinalResult(AlgorithmNodePacket job, Dictionary <int, Order> orders, Dictionary <DateTime, decimal> profitLoss, Dictionary <string, Holding> holdings, CashBook cashbook, StatisticsResults statisticsResults, Dictionary <string, string> banner) { }
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 symbol1 = quoteCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.IsNotNull(symbol1); Assert.AreEqual(quoteCurrencySymbol, symbol1.Symbol.Value); var symbol2 = baseCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.IsNotNull(symbol2); Assert.AreEqual(baseCurrencySymbol, symbol2.Symbol.Value); }
public void ComputesValueInAccountCurrency() { var book = new CashBook(); book["USD"].SetAmount(1000); book.Add("JPY", 1000, 1/100m); book.Add("GBP", 1000, 2m); decimal expected = book["USD"].ValueInAccountCurrency + book["JPY"].ValueInAccountCurrency + book["GBP"].ValueInAccountCurrency; Assert.AreEqual(expected, book.TotalValueInAccountCurrency); }
public void ConvertsProperly() { var book = new CashBook(); book.Add("EUR", 0, 1.10m); book.Add("GBP", 0, 0.71m); var expected = 781m; var actual = book.Convert(1000, "EUR", "GBP"); Assert.AreEqual(expected, actual); }
public EditReciept(CashBook frm1) { owner = frm1; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AddReciept_FormClosing); //caller = new StackTrace().GetFrame(1).GetMethod().DeclaringType.Name; InitializeComponent(); }
/// <summary> /// Constructor for the result class for dictionary objects /// </summary> public LiveResult(IDictionary <string, Chart> charts, IDictionary <int, Order> orders, IDictionary <DateTime, decimal> profitLoss, IDictionary <string, Holding> holdings, CashBook cashbook, IDictionary <string, string> statistics, IDictionary <string, string> runtime, IDictionary <string, string> serverStatistics = null) { Charts = charts; Orders = orders; ProfitLoss = profitLoss; Statistics = statistics; Holdings = holdings; Cash = cashbook; RuntimeStatistics = runtime; ServerStatistics = serverStatistics ?? OS.GetServerStatistics(); }
public void ConvertsToJpyFromAccountCurrencyProperly() { var book = new CashBook(); book.Add("JPY", 0, 1 / 100m); var expected = 100000m; var actual = book.Convert(1000, CashBook.AccountCurrency, "JPY"); Assert.AreEqual(expected, actual); }
public void ConvertsToEurFromAccountCurrencyProperly() { var book = new CashBook(); book.Add("EUR", 0, 1.20m); var expected = 1000m; var actual = book.Convert(1200, book.AccountCurrency, "EUR"); Assert.AreEqual(expected, actual); }
public void ComputesValueInBaseCurrency() { var book = new CashBook(); book["USD"].Quantity = 1000; book.Add("JPY", 1000, 1 / 100m); book.Add("GBP", 1000, 2m); decimal expected = book["USD"].ValueInBaseCurrency + book["JPY"].ValueInBaseCurrency + book["GBP"].ValueInBaseCurrency; Assert.AreEqual(expected, book.ValueInBaseCurrency); }
private static void Update(CashBook cashBook, Security security, decimal close) { security.SetMarketPrice(new TradeBar { Time = DateTime.Now, Symbol = security.Symbol, Open = close, High = close, Low = close, Close = close }); }
/// <summary> /// Constructor for the result class for dictionary objects /// </summary> public LiveResult(LiveResultParameters parameters) { Charts = parameters.Charts; Orders = parameters.Orders; ProfitLoss = parameters.ProfitLoss; Statistics = parameters.Statistics; Holdings = parameters.Holdings; Cash = parameters.CashBook; RuntimeStatistics = parameters.RuntimeStatistics; ServerStatistics = parameters.ServerStatistics; AlphaRuntimeStatistics = parameters.AlphaRuntimeStatistics; }
public void ConvertsProperly() { var book = new CashBook(); book.Add("EUR", 0, 1.10m); book.Add("GBP", 0, 0.71m); var expected = 1549.2957746478873239436619718m; var actual = book.Convert(1000, "EUR", "GBP"); Assert.AreEqual(expected, actual); }
public void ComputesValueInAccountCurrency() { var book = new CashBook(); book["USD"].SetAmount(1000); book.Add("JPY", 1000, 1 / 100m); book.Add("GBP", 1000, 2m); decimal expected = book["USD"].ValueInAccountCurrency + book["JPY"].ValueInAccountCurrency + book["GBP"].ValueInAccountCurrency; Assert.AreEqual(expected, book.TotalValueInAccountCurrency); }
public void EnsureCurrencyDataFeedAddsSubscription() { 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(TimeKeeper); 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))); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); Assert.AreEqual(1, subscriptions.Subscriptions.Count(x => x.Symbol == Symbols.USDJPY)); Assert.AreEqual(1, securities.Values.Count(x => x.Symbol == Symbols.USDJPY)); }
public void UpdateModifiesConversionRate() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cash = new Cash("GBP", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("GBP", cash); var subscriptions = new SubscriptionManager(TimeKeeper); var securities = new SecurityManager(TimeKeeper); securities.Add(Symbols.GBPUSD, new Security(SecurityExchangeHours, subscriptions.Add(Symbols.GBPUSD, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); // we need to get subscription index cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); var last = 1.5m; cash.Update(new Tick(DateTime.Now, Symbols.GBPUSD, last, last * 1.009m, last * 0.009m)); // jpy is inverted, so compare on the inverse Assert.AreEqual(last, cash.ConversionRate); }
public void EnsureInternalCurrencyDataFeedsForNonUsdQuoteCurrencyGetAdded() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cashJPY = new Cash("JPY", quantity, conversionRate); var cashGBP = new Cash("GBP", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("JPY", cashJPY); cashBook.Add("GBP", cashGBP); var symbol = Symbol.Create("GBPJPY", SecurityType.Forex, Market.FXCM); var subscriptions = new SubscriptionManager(TimeKeeper); var securities = new SecurityManager(TimeKeeper); securities.Add(symbol, new Security(SecurityExchangeHours, subscriptions.Add(symbol, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); cashJPY.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); var config1 = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.USDJPY); Assert.IsTrue(config1.IsInternalFeed); cashGBP.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); var config2 = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.GBPUSD); Assert.IsTrue(config2.IsInternalFeed); }
public void EnsureCurrencyDataFeedDoesNotMarkIsCurrencyDataFeedForExistantSubscriptions() { 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(TimeKeeper); var securities = new SecurityManager(TimeKeeper); securities.Add(Symbols.USDJPY, new Security(SecurityExchangeHours, subscriptions.Add(Symbols.USDJPY, Resolution.Minute, TimeZone, TimeZone), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); var config = subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.USDJPY); Assert.IsFalse(config.IsInternalFeed); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<DataFeedPacket> data, SecurityChanges changes) { int count = 0; var security = new List<UpdateData<Security>>(); var custom = new List<UpdateData<Security>>(); var consolidator = new List<UpdateData<SubscriptionDataConfig>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<UpdateData<Cash>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; // we need to be able to reference the slice being created in order to define the // evaluation of option price models, so we define a 'future' that can be referenced // in the option price model evaluation delegates for each contract Slice slice = null; var sliceFuture = new Lazy<Slice>(() => slice); var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var quoteBars = new QuoteBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var optionChains = new OptionChains(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var packet in data) { var list = packet.Data; var symbol = packet.Security.Symbol; if (list.Count == 0) continue; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count; if (baseDataCollectionCount == 0) { continue; } count += baseDataCollectionCount; } else { count += list.Count; } if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData) { // This is all the custom data custom.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, list)); } var securityUpdate = new List<BaseData>(list.Count); var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!packet.Configuration.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!packet.Configuration.IsInternalFeed) { PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains); // special handling of options data to build the option chain if (packet.Security.Type == SecurityType.Option) { if (baseData.DataType == MarketDataType.OptionChain) { optionChains[baseData.Symbol] = (OptionChain) baseData; } else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture)) { continue; } } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices securityUpdate.Add(baseData); } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[packet.Configuration.Symbol] = symbolChange; } } if (securityUpdate.Count > 0) { // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (cashSecurities.Contains(packet.Security.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol) { var cashUpdates = new List<BaseData> {securityUpdate[securityUpdate.Count - 1]}; cash.Add(new UpdateData<Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates)); } } } security.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, securityUpdate)); } if (consolidatorUpdate.Count > 0) { consolidator.Add(new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate)); } } slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }
/// <summary> /// Ensures that we have a data feed to convert this currency into the base currency. /// This will add a subscription at the lowest resolution if one is not found. /// </summary> /// <param name="securities">The security manager</param> /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param> /// <param name="marketHoursDatabase">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param> /// <param name="symbolPropertiesDatabase">A symbol properties database instance</param> /// <param name="marketMap">The market map that decides which market the new security should be in</param> /// <param name="cashBook">The cash book - used for resolving quote currencies for created conversion securities</param> /// <returns>Returns the added currency security if needed, otherwise null</returns> public Security EnsureCurrencyDataFeed(SecurityManager securities, SubscriptionManager subscriptions, MarketHoursDatabase marketHoursDatabase, SymbolPropertiesDatabase symbolPropertiesDatabase, IReadOnlyDictionary<SecurityType, string> marketMap, CashBook cashBook) { if (Symbol == CashBook.AccountCurrency) { SecuritySymbol = QuantConnect.Symbol.Empty; _isBaseCurrency = true; ConversionRate = 1.0m; return null; } if (subscriptions.Count == 0) { throw new InvalidOperationException("Unable to add cash when no subscriptions are present. Please add subscriptions in the Initialize() method."); } // we require a subscription that converts this into the base currency string normal = Symbol + CashBook.AccountCurrency; string invert = CashBook.AccountCurrency + Symbol; foreach (var config in subscriptions.Subscriptions.Where(config => config.SecurityType == SecurityType.Forex || config.SecurityType == SecurityType.Cfd)) { if (config.Symbol.Value == normal) { SecuritySymbol = config.Symbol; return null; } if (config.Symbol.Value == invert) { SecuritySymbol = config.Symbol; _invertRealTimePrice = true; return null; } } // if we've made it here we didn't find a subscription, so we'll need to add one var currencyPairs = Currencies.CurrencyPairs.Select(x => { // allow XAU or XAG to be used as quote currencies, but pairs including them are CFDs var securityType = Symbol.StartsWith("X") ? SecurityType.Cfd : SecurityType.Forex; var market = marketMap[securityType]; return QuantConnect.Symbol.Create(x, securityType, market); }); var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(Resolution.Minute).Min(); var objectType = minimumResolution == Resolution.Tick ? typeof (Tick) : typeof (TradeBar); foreach (var symbol in currencyPairs) { if (symbol.Value == normal || symbol.Value == invert) { _invertRealTimePrice = symbol.Value == invert; var marketHoursDbEntry = marketHoursDatabase.GetEntry(symbol.ID.Market, symbol.Value, symbol.ID.SecurityType); var exchangeHours = marketHoursDbEntry.ExchangeHours; // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events var config = subscriptions.Add(objectType, symbol, minimumResolution, marketHoursDbEntry.DataTimeZone, exchangeHours.TimeZone, false, true, false, true); SecuritySymbol = config.Symbol; var securityType = symbol.ID.SecurityType; Security security; if (securityType == SecurityType.Cfd) { var symbolProperties = symbolPropertiesDatabase.GetSymbolProperties(symbol.ID.Market, symbol.Value, securityType); Cash quoteCash; if (!cashBook.TryGetValue(symbolProperties.QuoteCurrency, out quoteCash)) { throw new Exception("Unable to resolve quote cash: " + symbolProperties.QuoteCurrency + ". This is required to add conversion feed: " + symbol.ToString()); } security = new Cfd.Cfd(exchangeHours, quoteCash, config, symbolProperties); } else { security = new Forex.Forex(exchangeHours, this, config); } securities.Add(config.Symbol, security); Log.Trace("Cash.EnsureCurrencyDataFeed(): Adding " + symbol.Value + " for cash " + Symbol + " currency feed"); return security; } } // if this still hasn't been set then it's an error condition throw new ArgumentException(string.Format("In order to maintain cash in {0} you are required to add a subscription for Forex pair {0}{1} or {1}{0}", Symbol, CashBook.AccountCurrency)); }
public void UpdateModifiesConversionRateAsInvertedValue() { 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(TimeKeeper); var securities = new SecurityManager(TimeKeeper); securities.Add(Symbols.USDJPY, new Security(SecurityExchangeHours, subscriptions.Add(Symbols.USDJPY, Resolution.Minute, TimeZone, TimeZone))); // we need to get subscription index cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); var last = 120m; cash.Update(new Tick(DateTime.Now, Symbols.USDJPY, last, 119.95m, 120.05m)); // jpy is inverted, so compare on the inverse Assert.AreEqual(1 / last, cash.ConversionRate); }
/// <summary> /// Syncs the specifies subscriptions at the frontier time /// </summary> /// <param name="frontier">The time used for syncing, data in the future won't be included in this time slice</param> /// <param name="subscriptions">The subscriptions to sync</param> /// <param name="sliceTimeZone">The time zone of the created slice object</param> /// <param name="cashBook">The cash book, used for creating the cash book updates</param> /// <param name="nextFrontier">The next frontier time as determined by the first piece of data in the future ahead of the frontier. /// This value will equal DateTime.MaxValue when the subscriptions are all finished</param> /// <returns>A time slice for the specified frontier time</returns> public TimeSlice Sync(DateTime frontier, IEnumerable<Subscription> subscriptions, DateTimeZone sliceTimeZone, CashBook cashBook, out DateTime nextFrontier) { var changes = SecurityChanges.None; nextFrontier = DateTime.MaxValue; var earlyBirdTicks = nextFrontier.Ticks; var data = new List<DataFeedPacket>(); SecurityChanges newChanges; do { newChanges = SecurityChanges.None; foreach (var subscription in subscriptions) { if (subscription.EndOfStream) { OnSubscriptionFinished(subscription); continue; } // prime if needed if (subscription.Current == null) { if (!subscription.MoveNext()) { OnSubscriptionFinished(subscription); continue; } } var packet = new DataFeedPacket(subscription.Security); data.Add(packet); var configuration = subscription.Configuration; var offsetProvider = subscription.OffsetProvider; var currentOffsetTicks = offsetProvider.GetOffsetTicks(frontier); while (subscription.Current.EndTime.Ticks - currentOffsetTicks <= frontier.Ticks) { // we want bars rounded using their subscription times, we make a clone // so we don't interfere with the enumerator's internal logic var clone = subscription.Current.Clone(subscription.Current.IsFillForward); clone.Time = clone.Time.ExchangeRoundDown(configuration.Increment, subscription.Security.Exchange.Hours, configuration.ExtendedMarketHours); packet.Add(clone); if (!subscription.MoveNext()) { OnSubscriptionFinished(subscription); break; } } // we have new universe data to select based on if (subscription.IsUniverseSelectionSubscription && packet.Count > 0) { // assume that if the first item is a base data collection then the enumerator handled the aggregation, // otherwise, load all the the data into a new collection instance var collection = packet.Data[0] as BaseDataCollection ?? new BaseDataCollection(frontier, subscription.Configuration.Symbol, packet.Data); newChanges += _universeSelection.ApplyUniverseSelection(subscription.Universe, frontier, collection); } if (subscription.Current != null) { // take the earliest between the next piece of data or the next tz discontinuity earlyBirdTicks = Math.Min(earlyBirdTicks, Math.Min(subscription.Current.EndTime.Ticks - currentOffsetTicks, offsetProvider.GetNextDiscontinuity())); } } changes += newChanges; } while (newChanges != SecurityChanges.None); nextFrontier = new DateTime(Math.Max(earlyBirdTicks, frontier.Ticks), DateTimeKind.Utc); return TimeSlice.Create(frontier, sliceTimeZone, cashBook, data, changes); }
public void EnsureCurrencyDataFeedsAddsSubscriptionAtMinimumResolution() { const int quantity = 100; const decimal conversionRate = 1 / 100m; const Resolution minimumResolution = Resolution.Second; var cash = new Cash("JPY", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("JPY", cash); var subscriptions = new SubscriptionManager(TimeKeeper); var securities = new SecurityManager(TimeKeeper); securities.Add(Symbols.SPY, new Security(SecurityExchangeHours, subscriptions.Add(Symbols.SPY, Resolution.Minute, TimeZone, TimeZone))); securities.Add(Symbols.EURUSD, new Security(SecurityExchangeHours, subscriptions.Add(Symbols.EURUSD, minimumResolution, TimeZone, TimeZone))); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); Assert.AreEqual(minimumResolution, subscriptions.Subscriptions.Single(x => x.Symbol == Symbols.USDJPY).Resolution); }
public void EnsureCurrencyDataFeedAddsSubscriptionThrowsWhenZeroSubscriptionsPresent() { 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 securities = new SecurityManager(TimeKeeper); var subscriptions = new SubscriptionManager(TimeKeeper); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketHoursDatabase.AlwaysOpen, SymbolPropertiesDatabase.FromDataFolder(), MarketMap, cashBook); }
/// <summary> /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data /// </summary> /// <param name="utcDateTime">The UTC frontier date time</param> /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param> /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param> /// <param name="data">The data in this <see cref="TimeSlice"/></param> /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param> /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns> public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<KeyValuePair<Security, List<BaseData>>> data, SecurityChanges changes) { int count = 0; var security = new List<KeyValuePair<Security, BaseData>>(); var custom = new List<KeyValuePair<Security, List<BaseData>>>(); var consolidator = new List<KeyValuePair<SubscriptionDataConfig, List<BaseData>>>(); var allDataForAlgorithm = new List<BaseData>(data.Count); var cash = new List<KeyValuePair<Cash, BaseData>>(cashBook.Count); var cashSecurities = new HashSet<Symbol>(); foreach (var cashItem in cashBook.Values) { cashSecurities.Add(cashItem.SecuritySymbol); } Split split; Dividend dividend; Delisting delisting; SymbolChangedEvent symbolChange; var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone); var tradeBars = new TradeBars(algorithmTime); var ticks = new Ticks(algorithmTime); var splits = new Splits(algorithmTime); var dividends = new Dividends(algorithmTime); var delistings = new Delistings(algorithmTime); var symbolChanges = new SymbolChangedEvents(algorithmTime); foreach (var kvp in data) { var list = kvp.Value; var symbol = kvp.Key.Symbol; // keep count of all data points if (list.Count == 1 && list[0] is BaseDataCollection) { count += ((BaseDataCollection) list[0]).Data.Count; } else { count += list.Count; } BaseData update = null; var consolidatorUpdate = new List<BaseData>(list.Count); for (int i = 0; i < list.Count; i++) { var baseData = list[i]; if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // this is all the data that goes into the algorithm allDataForAlgorithm.Add(baseData); if (kvp.Key.SubscriptionDataConfig.IsCustomData) { // this is all the custom data custom.Add(kvp); } } // don't add internal feed data to ticks/bars objects if (baseData.DataType != MarketDataType.Auxiliary) { if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed) { // populate ticks and tradebars dictionaries with no aux data if (baseData.DataType == MarketDataType.Tick) { List<Tick> ticksList; if (!ticks.TryGetValue(symbol, out ticksList)) { ticksList = new List<Tick> {(Tick) baseData}; ticks[symbol] = ticksList; } ticksList.Add((Tick) baseData); } else if (baseData.DataType == MarketDataType.TradeBar) { tradeBars[symbol] = (TradeBar) baseData; } // this is data used to update consolidators consolidatorUpdate.Add(baseData); } // this is the data used set market prices update = baseData; } // include checks for various aux types so we don't have to construct the dictionaries in Slice else if ((delisting = baseData as Delisting) != null) { delistings[symbol] = delisting; } else if ((dividend = baseData as Dividend) != null) { dividends[symbol] = dividend; } else if ((split = baseData as Split) != null) { splits[symbol] = split; } else if ((symbolChange = baseData as SymbolChangedEvent) != null) { // symbol changes is keyed by the requested symbol symbolChanges[kvp.Key.SubscriptionDataConfig.Symbol] = symbolChange; } } // check for 'cash securities' if we found valid update data for this symbol // and we need this data to update cash conversion rates, long term we should // have Cash hold onto it's security, then he can update himself, or rather, just // patch through calls to conversion rate to compue it on the fly using Security.Price if (update != null && cashSecurities.Contains(kvp.Key.Symbol)) { foreach (var cashKvp in cashBook) { if (cashKvp.Value.SecuritySymbol == kvp.Key.Symbol) { cash.Add(new KeyValuePair<Cash, BaseData>(cashKvp.Value, update)); } } } security.Add(new KeyValuePair<Security, BaseData>(kvp.Key, update)); consolidator.Add(new KeyValuePair<SubscriptionDataConfig, List<BaseData>>(kvp.Key.SubscriptionDataConfig, consolidatorUpdate)); } var slice = new Slice(utcDateTime.ConvertFromUtc(algorithmTimeZone), allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0); return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes); }