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