/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; namespace QuantConnect { /// /// Markets Collection: Soon to be expanded to a collection of items specifying the market hour, timezones and country codes. /// public static class Market { // the upper bound (non-inclusive) for market identifiers private const int MaxMarketIdentifier = 1000; private static readonly object _lock = new object(); private static readonly Dictionary Markets = new Dictionary(); private static readonly Dictionary ReverseMarkets = new Dictionary(); private static readonly IEnumerable> HardcodedMarkets = new List> { Tuple.Create("empty", 0), Tuple.Create(USA, 1), Tuple.Create(FXCM, 2), Tuple.Create(Oanda, 3), Tuple.Create(Dukascopy, 4), Tuple.Create(Bitfinex, 5), Tuple.Create(Globex, 6), Tuple.Create(NYMEX, 7), Tuple.Create(CBOT, 8), Tuple.Create(ICE, 9), Tuple.Create(CBOE, 10), Tuple.Create(NSE, 11), Tuple.Create(GDAX, 12), Tuple.Create(Kraken, 13), Tuple.Create(Bittrex, 14), Tuple.Create(Bithumb, 15), Tuple.Create(Binance, 16), Tuple.Create(Poloniex, 17), Tuple.Create(Coinone, 18), Tuple.Create(HitBTC, 19), Tuple.Create(OkCoin, 20), Tuple.Create(Bitstamp, 21), Tuple.Create(COMEX, 22), Tuple.Create(CME, 23), Tuple.Create(SGX, 24), Tuple.Create(HKFE, 25), }; static Market() { // initialize our maps foreach (var market in HardcodedMarkets) { Markets[market.Item1] = market.Item2; ReverseMarkets[market.Item2] = market.Item1; } } /// /// USA Market /// public const string USA = "usa"; /// /// Oanda Market /// public const string Oanda = "oanda"; /// /// FXCM Market Hours /// public const string FXCM = "fxcm"; /// /// Dukascopy Market /// public const string Dukascopy = "dukascopy"; /// /// Bitfinex market /// public const string Bitfinex = "bitfinex"; // Futures exchanges /// /// CME Globex /// public const string Globex = "cmeglobex"; /// /// NYMEX /// public const string NYMEX = "nymex"; /// /// CBOT /// public const string CBOT = "cbot"; /// /// ICE /// public const string ICE = "ice"; /// /// CBOE /// public const string CBOE = "cboe"; /// /// NSE /// public const string NSE = "nse"; /// /// Comex /// public const string COMEX = "comex"; /// /// CME /// public const string CME = "cme"; /// /// Singapore Exchange /// public const string SGX = "sgx"; /// /// Hong Kong Exchange /// public const string HKFE = "hkfe"; /// /// GDAX /// public const string GDAX = "gdax"; /// /// Kraken /// public const string Kraken = "kraken"; /// /// Bitstamp /// public const string Bitstamp = "bitstamp"; /// /// OkCoin /// public const string OkCoin = "okcoin"; /// /// Bithumb /// public const string Bithumb = "bithumb"; /// /// Binance /// public const string Binance = "binance"; /// /// Poloniex /// public const string Poloniex = "poloniex"; /// /// Coinone /// public const string Coinone = "coinone"; /// /// HitBTC /// public const string HitBTC = "hitbtc"; /// /// Bittrex /// public const string Bittrex = "bittrex"; /// /// Adds the specified market to the map of available markets with the specified identifier. /// /// The market string to add /// The identifier for the market, this value must be positive and less than 1000 public static void Add(string market, int identifier) { if (identifier >= MaxMarketIdentifier) { throw new ArgumentOutOfRangeException(nameof(identifier), $"The market identifier is limited to positive values less than {MaxMarketIdentifier.ToStringInvariant()}." ); } market = market.ToLowerInvariant(); // we lock since we don't want multiple threads getting these two dictionaries out of sync lock (_lock) { int marketIdentifier; if (Markets.TryGetValue(market, out marketIdentifier) && identifier != marketIdentifier) { throw new ArgumentException( $"Attempted to add an already added market with a different identifier. Market: {market}" ); } string existingMarket; if (ReverseMarkets.TryGetValue(identifier, out existingMarket)) { throw new ArgumentException( "Attempted to add a market identifier that is already in use. " + $"New Market: {market} Existing Market: {existingMarket}" ); } // update our maps Markets[market] = identifier; ReverseMarkets[identifier] = market; } } /// /// Gets the market code for the specified market. Returns null if the market is not found /// /// The market to check for (case sensitive) /// The internal code used for the market. Corresponds to the value used when calling public static int? Encode(string market) { lock (_lock) { int code; return !Markets.TryGetValue(market, out code) ? (int?) null : code; } } /// /// Gets the market string for the specified market code. /// /// The market code to be decoded /// The string representation of the market, or null if not found public static string Decode(int code) { lock (_lock) { string market; return !ReverseMarkets.TryGetValue(code, out market) ? null : market; } } } }