Lean  $LEAN_TAG$
Market.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using System.Linq;
18 using System.Collections.Generic;
19 
20 namespace QuantConnect
21 {
22  /// <summary>
23  /// Markets Collection: Soon to be expanded to a collection of items specifying the market hour, timezones and country codes.
24  /// </summary>
25  public static class Market
26  {
27  // the upper bound (non-inclusive) for market identifiers
28  private const int MaxMarketIdentifier = 1000;
29 
30  private static Dictionary<string, int> Markets = new Dictionary<string, int>();
31  private static Dictionary<int, string> ReverseMarkets = new Dictionary<int, string>();
32  private static readonly IEnumerable<Tuple<string, int>> HardcodedMarkets = new List<Tuple<string, int>>
33  {
34  Tuple.Create("empty", 0),
35  Tuple.Create(USA, 1),
36  Tuple.Create(FXCM, 2),
37  Tuple.Create(Oanda, 3),
38  Tuple.Create(Dukascopy, 4),
39  Tuple.Create(Bitfinex, 5),
40 
41  Tuple.Create(Globex, 6),
42  Tuple.Create(NYMEX, 7),
43  Tuple.Create(CBOT, 8),
44  Tuple.Create(ICE, 9),
45  Tuple.Create(CBOE, 10),
46  Tuple.Create(India, 11),
47 
48  Tuple.Create(GDAX, 12),
49  Tuple.Create(Kraken, 13),
50  Tuple.Create(Bittrex, 14),
51  Tuple.Create(Bithumb, 15),
52  Tuple.Create(Binance, 16),
53  Tuple.Create(Poloniex, 17),
54  Tuple.Create(Coinone, 18),
55  Tuple.Create(HitBTC, 19),
56  Tuple.Create(OkCoin, 20),
57  Tuple.Create(Bitstamp, 21),
58 
59  Tuple.Create(COMEX, 22),
60  Tuple.Create(CME, 23),
61  Tuple.Create(SGX, 24),
62  Tuple.Create(HKFE, 25),
63  Tuple.Create(NYSELIFFE, 26),
64 
65  Tuple.Create(CFE, 33),
66  Tuple.Create(FTX, 34),
67  Tuple.Create(FTXUS, 35),
68  Tuple.Create(BinanceUS, 36),
69  Tuple.Create(Bybit, 37),
70  Tuple.Create(Coinbase, 38),
71  Tuple.Create(InteractiveBrokers, 39),
72  Tuple.Create(EUREX, 40),
73  Tuple.Create(OSE, 41)
74  };
75 
76  static Market()
77  {
78  // initialize our maps
79  foreach (var market in HardcodedMarkets)
80  {
81  Markets[market.Item1] = market.Item2;
82  ReverseMarkets[market.Item2] = market.Item1;
83  }
84  }
85 
86  /// <summary>
87  /// USA Market
88  /// </summary>
89  public const string USA = "usa";
90 
91  /// <summary>
92  /// Oanda Market
93  /// </summary>
94  public const string Oanda = "oanda";
95 
96  /// <summary>
97  /// FXCM Market Hours
98  /// </summary>
99  public const string FXCM = "fxcm";
100 
101  /// <summary>
102  /// Dukascopy Market
103  /// </summary>
104  public const string Dukascopy = "dukascopy";
105 
106  /// <summary>
107  /// Bitfinex market
108  /// </summary>
109  public const string Bitfinex = "bitfinex";
110 
111  // Futures exchanges
112 
113  /// <summary>
114  /// CME Globex
115  /// </summary>
116  public const string Globex = "cmeglobex";
117 
118  /// <summary>
119  /// NYMEX
120  /// </summary>
121  public const string NYMEX = "nymex";
122 
123  /// <summary>
124  /// CBOT
125  /// </summary>
126  public const string CBOT = "cbot";
127 
128  /// <summary>
129  /// ICE
130  /// </summary>
131  public const string ICE = "ice";
132 
133  /// <summary>
134  /// CBOE
135  /// </summary>
136  public const string CBOE = "cboe";
137 
138  /// <summary>
139  /// CFE
140  /// </summary>
141  public const string CFE = "cfe";
142 
143  /// <summary>
144  /// NSE - National Stock Exchange
145  /// </summary>
146  public const string India = "india";
147 
148  /// <summary>
149  /// Comex
150  /// </summary>
151  public const string COMEX = "comex";
152 
153  /// <summary>
154  /// CME
155  /// </summary>
156  public const string CME = "cme";
157 
158  /// <summary>
159  /// EUREX
160  /// </summary>
161  public const string EUREX = "eurex";
162 
163  /// <summary>
164  /// Singapore Exchange
165  /// </summary>
166  public const string SGX = "sgx";
167 
168  /// <summary>
169  /// Hong Kong Exchange
170  /// </summary>
171  public const string HKFE = "hkfe";
172 
173  /// <summary>
174  /// Osaka Stock Exchange
175  /// </summary>
176  public const string OSE = "ose";
177 
178  /// <summary>
179  /// London International Financial Futures and Options Exchange
180  /// </summary>
181  public const string NYSELIFFE = "nyseliffe";
182 
183  /// <summary>
184  /// GDAX
185  /// </summary>
186  [Obsolete("The GDAX constant is deprecated. Please use Coinbase instead.")]
187  public const string GDAX = Coinbase;
188 
189  /// <summary>
190  /// Kraken
191  /// </summary>
192  public const string Kraken = "kraken";
193 
194  /// <summary>
195  /// Bitstamp
196  /// </summary>
197  public const string Bitstamp = "bitstamp";
198 
199  /// <summary>
200  /// OkCoin
201  /// </summary>
202  public const string OkCoin = "okcoin";
203 
204  /// <summary>
205  /// Bithumb
206  /// </summary>
207  public const string Bithumb = "bithumb";
208 
209  /// <summary>
210  /// Binance
211  /// </summary>
212  public const string Binance = "binance";
213 
214  /// <summary>
215  /// Poloniex
216  /// </summary>
217  public const string Poloniex = "poloniex";
218 
219  /// <summary>
220  /// Coinone
221  /// </summary>
222  public const string Coinone = "coinone";
223 
224  /// <summary>
225  /// HitBTC
226  /// </summary>
227  public const string HitBTC = "hitbtc";
228 
229  /// <summary>
230  /// Bittrex
231  /// </summary>
232  public const string Bittrex = "bittrex";
233 
234  /// <summary>
235  /// FTX
236  /// </summary>
237  public const string FTX = "ftx";
238 
239  /// <summary>
240  /// FTX.US
241  /// </summary>
242  public const string FTXUS = "ftxus";
243 
244  /// <summary>
245  /// Binance.US
246  /// </summary>
247  public const string BinanceUS = "binanceus";
248 
249  /// <summary>
250  /// Bybit
251  /// </summary>
252  public const string Bybit = "bybit";
253 
254  /// <summary>
255  /// Coinbase
256  /// </summary>
257  public const string Coinbase = "coinbase";
258 
259  /// <summary>
260  /// InteractiveBrokers market
261  /// </summary>
262  public const string InteractiveBrokers = "interactivebrokers";
263 
264  /// <summary>
265  /// Adds the specified market to the map of available markets with the specified identifier.
266  /// </summary>
267  /// <param name="market">The market string to add</param>
268  /// <param name="identifier">The identifier for the market, this value must be positive and less than 1000</param>
269  public static void Add(string market, int identifier)
270  {
271  if (identifier >= MaxMarketIdentifier)
272  {
273  throw new ArgumentOutOfRangeException(nameof(identifier), Messages.Market.InvalidMarketIdentifier(MaxMarketIdentifier));
274  }
275 
276  market = market.ToLowerInvariant();
277 
278  int marketIdentifier;
279  if (Markets.TryGetValue(market, out marketIdentifier) && identifier != marketIdentifier)
280  {
281  throw new ArgumentException(Messages.Market.TriedToAddExistingMarketWithDifferentIdentifier(market));
282  }
283 
284  string existingMarket;
285  if (ReverseMarkets.TryGetValue(identifier, out existingMarket))
286  {
287  throw new ArgumentException(Messages.Market.TriedToAddExistingMarketIdentifier(market, existingMarket));
288  }
289 
290  // update our maps.
291  // We make a copy and update the copy, later swap the references so it's thread safe with no lock
292  var newMarketDictionary = Markets.ToDictionary(entry => entry.Key,
293  entry => entry.Value);
294  newMarketDictionary[market] = identifier;
295 
296  var newReverseMarketDictionary = ReverseMarkets.ToDictionary(entry => entry.Key,
297  entry => entry.Value);
298  newReverseMarketDictionary[identifier] = market;
299 
300  Markets = newMarketDictionary;
301  ReverseMarkets = newReverseMarketDictionary;
302  }
303 
304  /// <summary>
305  /// Gets the market code for the specified market. Returns <c>null</c> if the market is not found
306  /// </summary>
307  /// <param name="market">The market to check for (case sensitive)</param>
308  /// <returns>The internal code used for the market. Corresponds to the value used when calling <see cref="Add"/></returns>
309  public static int? Encode(string market)
310  {
311  return !Markets.TryGetValue(market, out var code) ? null : code;
312  }
313 
314  /// <summary>
315  /// Gets the market string for the specified market code.
316  /// </summary>
317  /// <param name="code">The market code to be decoded</param>
318  /// <returns>The string representation of the market, or null if not found</returns>
319  public static string Decode(int code)
320  {
321  return !ReverseMarkets.TryGetValue(code, out var market) ? null : market;
322  }
323 
324  /// <summary>
325  /// Returns a list of the supported markets
326  /// </summary>
327  public static List<string> SupportedMarkets()
328  {
329  return Markets.Keys.ToList();
330  }
331  }
332 }