/// <summary> /// Set SymbolProperties entry for a particular market, symbol and security type. /// </summary> /// <param name="market">Market of the entry</param> /// <param name="symbol">Symbol of the entry</param> /// <param name="securityType">Type of security for the entry</param> /// <param name="properties">The new symbol properties to store</param> /// <returns>True if successful</returns> public bool SetEntry(string market, string symbol, SecurityType securityType, SymbolProperties properties) { var key = new SecurityDatabaseKey(market, symbol, securityType); _entries[key] = properties; return(true); }
/// <summary> /// Gets the entry for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <returns>The entry matching the specified market/symbol/security-type</returns> public virtual Entry GetEntry(string market, string symbol, SecurityType securityType) { Entry entry; // Fall back on the Futures MHDB entry if the FOP lookup failed. // Some FOPs have the same symbol properties as their futures counterparts. // So, to save ourselves some space, we can fall back on the existing entries // so that we don't duplicate the information. if (!TryGetEntry(market, symbol, securityType, out entry) && !(securityType == SecurityType.FutureOption && TryGetEntry(market, FuturesOptionsSymbolMappings.MapFromOption(symbol), SecurityType.Future, out entry))) { var key = new SecurityDatabaseKey(market, symbol, securityType); var keys = string.Join(", ", _entries.Keys); Log.Error($"MarketHoursDatabase.GetExchangeHours(): Unable to locate exchange hours for {key}.Available keys: {keys}"); if (securityType == SecurityType.Future && market == Market.USA) { var exception = "Future.Usa market type is no longer supported as we mapped each ticker to its actual exchange. " + "Please find your specific market in the symbol-properties database."; if (SymbolPropertiesDatabase.FromDataFolder().TryGetMarket(symbol, SecurityType.Future, out market)) { // let's suggest a market exception += $" Suggested market based on the provided ticker 'Market.{market.ToUpperInvariant()}'."; } throw new ArgumentException(exception); } // there was nothing that really matched exactly throw new ArgumentException($"Unable to locate exchange hours for {key}"); } return(entry); }
/// <summary> /// Gets the entry for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <returns>The entry matching the specified market/symbol/security-type</returns> public virtual Entry GetEntry(string market, string symbol, SecurityType securityType) { Entry entry; if (!TryGetEntry(market, symbol, securityType, out entry)) { var key = new SecurityDatabaseKey(market, symbol, securityType); var keys = string.Join(", ", _entries.Keys); Log.Error($"MarketHoursDatabase.GetExchangeHours(): Unable to locate exchange hours for {key}.Available keys: {keys}"); if (securityType == SecurityType.Future && market == Market.USA) { var exception = "Future.Usa market type is no longer supported as we mapped each ticker to its actual exchange. " + "Please find your specific market in the symbol-properties database."; if (SymbolPropertiesDatabase.FromDataFolder().TryGetMarket(symbol, SecurityType.Future, out market)) { // let's suggest a market exception += $" Suggested market based on the provided ticker 'Market.{market.ToUpperInvariant()}'."; } throw new ArgumentException(exception); } // there was nothing that really matched exactly throw new ArgumentException($"Unable to locate exchange hours for {key}"); } return(entry); }
/// <summary> /// Gets the symbol properties for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded (Symbol class)</param> /// <param name="securityType">The security type of the symbol</param> /// <param name="defaultQuoteCurrency">Specifies the quote currency to be used when returning a default instance of an entry is not found in the database</param> /// <returns>The symbol properties matching the specified market/symbol/security-type or null if not found</returns> /// <remarks>For any derivative options asset that is not for equities, we default to the underlying symbol's properties if no entry is found in the database</remarks> public SymbolProperties GetSymbolProperties(string market, Symbol symbol, SecurityType securityType, string defaultQuoteCurrency) { SymbolProperties symbolProperties; var lookupTicker = MarketHoursDatabase.GetDatabaseSymbolKey(symbol); var key = new SecurityDatabaseKey(market, lookupTicker, securityType); if (!_entries.TryGetValue(key, out symbolProperties)) { if (symbol != null && symbol.SecurityType == SecurityType.FutureOption) { // Default to looking up the underlying symbol's properties and using those instead if there's // no existing entry for the future option. lookupTicker = MarketHoursDatabase.GetDatabaseSymbolKey(symbol.Underlying); key = new SecurityDatabaseKey(market, lookupTicker, symbol.Underlying.SecurityType); if (_entries.TryGetValue(key, out symbolProperties)) { return(symbolProperties); } } // now check with null symbol key if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out symbolProperties)) { // no properties found, return object with default property values return(SymbolProperties.GetDefault(defaultQuoteCurrency)); } } return(symbolProperties); }
/// <summary> /// Creates a new instance of <see cref="SymbolProperties"/> from the specified csv line /// </summary> /// <param name="line">The csv line to be parsed</param> /// <param name="key">The key used to uniquely identify this security</param> /// <returns>A new <see cref="SymbolProperties"/> for the specified csv line</returns> protected static SymbolProperties FromCsvLine(string line, out SecurityDatabaseKey key) { var csv = line.Split(','); SecurityType securityType; if (!csv[2].TryParseSecurityType(out securityType)) { key = null; return(null); } key = new SecurityDatabaseKey( market: csv[0], symbol: csv[1], securityType: securityType); return(new SymbolProperties( description: csv[3], quoteCurrency: csv[4], contractMultiplier: csv[5].ToDecimal(), minimumPriceVariation: csv[6].ToDecimalAllowExponent(), lotSize: csv[7].ToDecimal(), marketTicker: csv.Length > 8 ? csv[8] : string.Empty)); }
/// <summary> /// Gets the instance of the <see cref="MarketHoursDatabase"/> class produced by reading in the market hours /// data found in /Data/market-hours/ /// </summary> /// <param name="dataFolder">Path to the data folder</param> /// <returns>A <see cref="MarketHoursDatabase"/> class that represents the data in the market-hours folder</returns> public static MarketHoursDatabase FromDataFolder(string dataFolder) { lock (DataFolderMarketHoursDatabaseLock) { if (_dataFolderMarketHoursDatabase == null) { var path = Path.Combine(dataFolder, "market-hours", "market-hours-database.json"); _dataFolderMarketHoursDatabase = FromFile(path); // Add markets not already present Market.Reset(); var listing = _dataFolderMarketHoursDatabase.ExchangeHoursListing; int code = 0; foreach (var item in listing) { SecurityDatabaseKey security = item.Key; string market = security.Market; if (Market.Encode(market) == null) { while (Market.Decode(code) != null) { code++; } // be sure to add a reference to the unknown market, otherwise we won't be able to decode it coming out Market.Add(market, code); code++; } } } } return(_dataFolderMarketHoursDatabase); }
/// <summary> /// Sets the entry for the specified market/symbol/security-type. /// This is intended to be used by custom data and other data sources that don't have explicit /// entries in market-hours-database.csv. At run time, the algorithm can update the market hours /// database via calls to AddData. /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <param name="exchangeHours">The exchange hours for the specified symbol</param> /// <param name="dataTimeZone">The time zone of the symbol's raw data. Optional, defaults to the exchange time zone</param> /// <returns>The entry matching the specified market/symbol/security-type</returns> public virtual Entry SetEntry(string market, string symbol, SecurityType securityType, SecurityExchangeHours exchangeHours, DateTimeZone dataTimeZone = null) { dataTimeZone = dataTimeZone ?? exchangeHours.TimeZone; var key = new SecurityDatabaseKey(market, symbol, securityType); var entry = new Entry(dataTimeZone, exchangeHours); _entries[key] = entry; return(entry); }
public override Entry GetEntry(string market, string symbol, SecurityType securityType) { var key = new SecurityDatabaseKey(market, symbol, securityType); var tz = ContainsKey(key) ? base.GetEntry(market, symbol, securityType).ExchangeHours.TimeZone : DateTimeZone.Utc; return(new Entry(tz, SecurityExchangeHours.AlwaysOpen(tz))); }
/// <summary> /// Tries to get the market for the provided symbol/security type /// </summary> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <param name="market">The market the exchange resides in <see cref="Market"/></param> /// <returns>True if market was retrieved, false otherwise</returns> public bool TryGetMarket(string symbol, SecurityType securityType, out string market) { SecurityDatabaseKey result; var key = new SecurityDatabaseKey(SecurityDatabaseKey.Wildcard, symbol, securityType); if (_keyBySecurityType.TryGetValue(key, out result)) { market = result.Market; return(true); } market = null; return(false); }
/// <summary> /// Creates a new instance of <see cref="SymbolProperties"/> from the specified csv line /// </summary> /// <param name="line">The csv line to be parsed</param> /// <param name="key">The key used to uniquely identify this security</param> /// <returns>A new <see cref="SymbolProperties"/> for the specified csv line</returns> private static SymbolProperties FromCsvLine(string line, out SecurityDatabaseKey key) { var csv = line.Split(','); key = new SecurityDatabaseKey( market: csv[0], symbol: string.IsNullOrEmpty(csv[1]) ? null : csv[1], securityType: (SecurityType)Enum.Parse(typeof(SecurityType), csv[2], true)); return(new SymbolProperties( description: csv[3], quoteCurrency: csv[4], contractMultiplier: csv[5].ToDecimal(), pipSize: csv[6].ToDecimal())); }
/// <summary> /// Creates a new instance of <see cref="SymbolProperties"/> from the specified csv line /// </summary> /// <param name="line">The csv line to be parsed</param> /// <param name="key">The key used to uniquely identify this security</param> /// <returns>A new <see cref="SymbolProperties"/> for the specified csv line</returns> private static SymbolProperties FromCsvLine(string line, out SecurityDatabaseKey key) { var csv = line.Split(','); key = new SecurityDatabaseKey( market: csv[0], symbol: csv[1], securityType: (SecurityType)Enum.Parse(typeof(SecurityType), csv[2], true)); return(new SymbolProperties( description: csv[3], quoteCurrency: csv[4], contractMultiplier: csv[5].ToDecimal(), minimumPriceVariation: csv[6].ToDecimalAllowExponent(), lotSize: csv[7].ToDecimal())); }
/// <summary> /// Gets the symbol properties for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <param name="defaultQuoteCurrency">Specifies the quote currency to be used when returning a default instance of an entry is not found in the database</param> /// <returns>The symbol properties matching the specified market/symbol/security-type or null if not found</returns> public SymbolProperties GetSymbolProperties(string market, string symbol, SecurityType securityType, string defaultQuoteCurrency) { SymbolProperties symbolProperties; var key = new SecurityDatabaseKey(market, symbol, securityType); if (!_entries.TryGetValue(key, out symbolProperties)) { // now check with null symbol key if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out symbolProperties)) { // no properties found, return object with default property values return(SymbolProperties.GetDefault(defaultQuoteCurrency)); } } return(symbolProperties); }
/// <summary> /// Gets the entry for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <returns>The entry matching the specified market/symbol/security-type</returns> public virtual Entry GetEntry(string market, string symbol, SecurityType securityType) { Entry entry; var key = new SecurityDatabaseKey(market, symbol, securityType); if (!_entries.TryGetValue(key, out entry)) { // now check with null symbol key if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out entry)) { var keys = string.Join(", ", _entries.Keys); Log.Error($"MarketHoursDatabase.GetExchangeHours(): Unable to locate exchange hours for {key}.Available keys: {keys}"); // there was nothing that really matched exactly... what should we do here? throw new ArgumentException("Unable to locate exchange hours for " + key); } } return(entry); }
/// <summary> /// Gets the symbol properties for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <returns>The symbol properties matching the specified market/symbol/security-type or null if not found</returns> public SymbolProperties GetSymbolProperties(string market, string symbol, SecurityType securityType) { SymbolProperties symbolProperties; var key = new SecurityDatabaseKey(market, symbol, securityType); if (!_entries.TryGetValue(key, out symbolProperties)) { // now check with null symbol key if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out symbolProperties)) { // no properties found, return object with default property values return(new SymbolProperties( description: "", quoteCurrency: "USD", contractMultiplier: 1m, pipSize: 0.01m)); } } return(symbolProperties); }
/// <summary> /// Gets the entry for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> /// <param name="overrideTimeZone">Specify this time zone to override the resolved time zone from the market hours database. /// This value will also be used as the time zone for SecurityType.Base with no market hours database entry. /// If null is specified, no override will be performed. If null is specified, and it's SecurityType.Base, then Utc will be used.</param> /// <returns>The entry matching the specified market/symbol/security-type</returns> public virtual Entry GetEntry(string market, string symbol, SecurityType securityType, DateTimeZone overrideTimeZone = null) { Entry entry; var key = new SecurityDatabaseKey(market, symbol, securityType); if (!_entries.TryGetValue(key, out entry)) { // now check with null symbol key if (!_entries.TryGetValue(new SecurityDatabaseKey(market, null, securityType), out entry)) { if (securityType == SecurityType.Base) { if (overrideTimeZone == null) { overrideTimeZone = TimeZones.Utc; Log.Error("MarketHoursDatabase.GetExchangeHours(): Custom data no time zone specified, default to UTC. " + key); } // base securities are always open by default and have equal data time zone and exchange time zones return(new Entry(overrideTimeZone, SecurityExchangeHours.AlwaysOpen(overrideTimeZone))); } Log.Error(string.Format("MarketHoursDatabase.GetExchangeHours(): Unable to locate exchange hours for {0}." + "Available keys: {1}", key, string.Join(", ", _entries.Keys))); // there was nothing that really matched exactly... what should we do here? throw new ArgumentException("Unable to locate exchange hours for " + key); } // perform time zone override if requested, we'll use the same exact local hours // and holidays, but we'll express them in a different time zone if (overrideTimeZone != null && !entry.ExchangeHours.TimeZone.Equals(overrideTimeZone)) { return(new Entry(overrideTimeZone, new SecurityExchangeHours(overrideTimeZone, entry.ExchangeHours.Holidays, entry.ExchangeHours.MarketHours, entry.ExchangeHours.EarlyCloses))); } } return(entry); }
private SymbolPropertiesDatabase(string file) { var allEntries = new Dictionary <SecurityDatabaseKey, SymbolProperties>(); var entriesBySecurityType = new Dictionary <SecurityDatabaseKey, SecurityDatabaseKey>(); foreach (var keyValuePair in FromCsvFile(file)) { if (allEntries.ContainsKey(keyValuePair.Key)) { throw new DuplicateNameException($"Encountered duplicate key while processing file: {file}. Key: {keyValuePair.Key}"); } // we wildcard the market, so per security type and symbol we will keep the *first* instance // this allows us to fetch deterministically, in O(1), an entry without knowing the market, see 'TryGetMarket()' var key = new SecurityDatabaseKey(SecurityDatabaseKey.Wildcard, keyValuePair.Key.Symbol, keyValuePair.Key.SecurityType); if (!entriesBySecurityType.ContainsKey(key)) { entriesBySecurityType[key] = keyValuePair.Key; } allEntries[keyValuePair.Key] = keyValuePair.Value; } _entries = allEntries; _keyBySecurityType = entriesBySecurityType; }
/// <summary> /// Determines if the database contains the specified key /// </summary> /// <param name="key">The key to search for</param> /// <returns>True if an entry is found, otherwise false</returns> protected bool ContainsKey(SecurityDatabaseKey key) { return(_entries.ContainsKey(key)); }
/// <summary> /// Check whether symbol properties exists for the specified market/symbol/security-type /// </summary> /// <param name="market">The market the exchange resides in, i.e, 'usa', 'fxcm', ect...</param> /// <param name="symbol">The particular symbol being traded</param> /// <param name="securityType">The security type of the symbol</param> public bool ContainsKey(string market, string symbol, SecurityType securityType) { var key = new SecurityDatabaseKey(market, symbol, securityType); return(_entries.ContainsKey(key)); }