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  };
73 
74  static Market()
75  {
76  // initialize our maps
77  foreach (var market in HardcodedMarkets)
78  {
79  Markets[market.Item1] = market.Item2;
80  ReverseMarkets[market.Item2] = market.Item1;
81  }
82  }
83 
84  /// <summary>
85  /// USA Market
86  /// </summary>
87  public const string USA = "usa";
88 
89  /// <summary>
90  /// Oanda Market
91  /// </summary>
92  public const string Oanda = "oanda";
93 
94  /// <summary>
95  /// FXCM Market Hours
96  /// </summary>
97  public const string FXCM = "fxcm";
98 
99  /// <summary>
100  /// Dukascopy Market
101  /// </summary>
102  public const string Dukascopy = "dukascopy";
103 
104  /// <summary>
105  /// Bitfinex market
106  /// </summary>
107  public const string Bitfinex = "bitfinex";
108 
109  // Futures exchanges
110 
111  /// <summary>
112  /// CME Globex
113  /// </summary>
114  public const string Globex = "cmeglobex";
115 
116  /// <summary>
117  /// NYMEX
118  /// </summary>
119  public const string NYMEX = "nymex";
120 
121  /// <summary>
122  /// CBOT
123  /// </summary>
124  public const string CBOT = "cbot";
125 
126  /// <summary>
127  /// ICE
128  /// </summary>
129  public const string ICE = "ice";
130 
131  /// <summary>
132  /// CBOE
133  /// </summary>
134  public const string CBOE = "cboe";
135 
136  /// <summary>
137  /// CFE
138  /// </summary>
139  public const string CFE = "cfe";
140 
141  /// <summary>
142  /// NSE - National Stock Exchange
143  /// </summary>
144  public const string India = "india";
145 
146  /// <summary>
147  /// Comex
148  /// </summary>
149  public const string COMEX = "comex";
150 
151  /// <summary>
152  /// CME
153  /// </summary>
154  public const string CME = "cme";
155 
156  /// <summary>
157  /// Singapore Exchange
158  /// </summary>
159  public const string SGX = "sgx";
160 
161  /// <summary>
162  /// Hong Kong Exchange
163  /// </summary>
164  public const string HKFE = "hkfe";
165 
166  /// <summary>
167  /// London International Financial Futures and Options Exchange
168  /// </summary>
169  public const string NYSELIFFE = "nyseliffe";
170 
171  /// <summary>
172  /// GDAX
173  /// </summary>
174  [Obsolete("The GDAX constant is deprecated. Please use Coinbase instead.")]
175  public const string GDAX = Coinbase;
176 
177  /// <summary>
178  /// Kraken
179  /// </summary>
180  public const string Kraken = "kraken";
181 
182  /// <summary>
183  /// Bitstamp
184  /// </summary>
185  public const string Bitstamp = "bitstamp";
186 
187  /// <summary>
188  /// OkCoin
189  /// </summary>
190  public const string OkCoin = "okcoin";
191 
192  /// <summary>
193  /// Bithumb
194  /// </summary>
195  public const string Bithumb = "bithumb";
196 
197  /// <summary>
198  /// Binance
199  /// </summary>
200  public const string Binance = "binance";
201 
202  /// <summary>
203  /// Poloniex
204  /// </summary>
205  public const string Poloniex = "poloniex";
206 
207  /// <summary>
208  /// Coinone
209  /// </summary>
210  public const string Coinone = "coinone";
211 
212  /// <summary>
213  /// HitBTC
214  /// </summary>
215  public const string HitBTC = "hitbtc";
216 
217  /// <summary>
218  /// Bittrex
219  /// </summary>
220  public const string Bittrex = "bittrex";
221 
222  /// <summary>
223  /// FTX
224  /// </summary>
225  public const string FTX = "ftx";
226 
227  /// <summary>
228  /// FTX.US
229  /// </summary>
230  public const string FTXUS = "ftxus";
231 
232  /// <summary>
233  /// Binance.US
234  /// </summary>
235  public const string BinanceUS = "binanceus";
236 
237  /// <summary>
238  /// Bybit
239  /// </summary>
240  public const string Bybit = "bybit";
241 
242  /// <summary>
243  /// Coinbase
244  /// </summary>
245  public const string Coinbase = "coinbase";
246 
247  /// <summary>
248  /// InteractiveBrokers market
249  /// </summary>
250  public const string InteractiveBrokers = "interactivebrokers";
251 
252  /// <summary>
253  /// Adds the specified market to the map of available markets with the specified identifier.
254  /// </summary>
255  /// <param name="market">The market string to add</param>
256  /// <param name="identifier">The identifier for the market, this value must be positive and less than 1000</param>
257  public static void Add(string market, int identifier)
258  {
259  if (identifier >= MaxMarketIdentifier)
260  {
261  throw new ArgumentOutOfRangeException(nameof(identifier), Messages.Market.InvalidMarketIdentifier(MaxMarketIdentifier));
262  }
263 
264  market = market.ToLowerInvariant();
265 
266  int marketIdentifier;
267  if (Markets.TryGetValue(market, out marketIdentifier) && identifier != marketIdentifier)
268  {
269  throw new ArgumentException(Messages.Market.TriedToAddExistingMarketWithDifferentIdentifier(market));
270  }
271 
272  string existingMarket;
273  if (ReverseMarkets.TryGetValue(identifier, out existingMarket))
274  {
275  throw new ArgumentException(Messages.Market.TriedToAddExistingMarketIdentifier(market, existingMarket));
276  }
277 
278  // update our maps.
279  // We make a copy and update the copy, later swap the references so it's thread safe with no lock
280  var newMarketDictionary = Markets.ToDictionary(entry => entry.Key,
281  entry => entry.Value);
282  newMarketDictionary[market] = identifier;
283 
284  var newReverseMarketDictionary = ReverseMarkets.ToDictionary(entry => entry.Key,
285  entry => entry.Value);
286  newReverseMarketDictionary[identifier] = market;
287 
288  Markets = newMarketDictionary;
289  ReverseMarkets = newReverseMarketDictionary;
290  }
291 
292  /// <summary>
293  /// Gets the market code for the specified market. Returns <c>null</c> if the market is not found
294  /// </summary>
295  /// <param name="market">The market to check for (case sensitive)</param>
296  /// <returns>The internal code used for the market. Corresponds to the value used when calling <see cref="Add"/></returns>
297  public static int? Encode(string market)
298  {
299  return !Markets.TryGetValue(market, out var code) ? null : code;
300  }
301 
302  /// <summary>
303  /// Gets the market string for the specified market code.
304  /// </summary>
305  /// <param name="code">The market code to be decoded</param>
306  /// <returns>The string representation of the market, or null if not found</returns>
307  public static string Decode(int code)
308  {
309  return !ReverseMarkets.TryGetValue(code, out var market) ? null : market;
310  }
311 
312  /// <summary>
313  /// Returns a list of the supported markets
314  /// </summary>
315  public static List<string> SupportedMarkets()
316  {
317  return Markets.Keys.ToList();
318  }
319  }
320 }