Lean  $LEAN_TAG$
Currencies.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.Collections.Generic;
18 using System.Linq;
19 using System.Globalization;
20 using System.Text.RegularExpressions;
21 
22 namespace QuantConnect
23 {
24  /// <summary>
25  /// Provides commonly used currency pairs and symbols
26  /// </summary>
27  public static class Currencies
28  {
29  /// <summary>
30  /// USD (United States Dollar) currency string
31  /// </summary>
32  public const string USD = "USD";
33 
34  /// <summary>
35  /// EUR (Euro) currency string
36  /// </summary>
37  public const string EUR = "EUR";
38 
39  /// <summary>
40  /// GBP (British pound sterling) currency string
41  /// </summary>
42  public const string GBP = "GBP";
43 
44  /// <summary>
45  /// INR (Indian rupee) currency string
46  /// </summary>
47  public const string INR = "INR";
48 
49  /// <summary>
50  /// IDR (Indonesian rupiah) currency string
51  /// </summary>
52  public const string IDR = "IDR";
53 
54  /// <summary>
55  /// CNH (Chinese Yuan Renminbi) currency string
56  /// </summary>
57  public const string CNH = "CNH";
58 
59  /// <summary>
60  /// CHF (Swiss Franc) currency string
61  /// </summary>
62  public const string CHF = "CHF";
63 
64  /// <summary>
65  /// HKD (Hong Kong dollar) currency string
66  /// </summary>
67  public const string HKD = "HKD";
68 
69  /// <summary>
70  /// JPY (Japanese yen) currency string
71  /// </summary>
72  public const string JPY = "JPY";
73 
74  /// <summary>
75  /// Null currency used when a real one is not required
76  /// </summary>
77  public const string NullCurrency = "QCC";
78 
79  /// <summary>
80  /// A mapping of currency codes to their display symbols
81  /// </summary>
82  /// <remarks>
83  /// Now used by Forex and CFD, should probably be moved out into its own class
84  /// </remarks>
85  public static readonly IReadOnlyDictionary<string, string> CurrencySymbols = new Dictionary<string, string>
86  {
87  {USD, "$"},
88  {GBP, "₤"},
89  {JPY, "¥"},
90  {EUR, "€"},
91  {"NZD", "$"},
92  {"AUD", "$"},
93  {"CAD", "$"},
94  {CHF, "Fr"},
95  {HKD, "$"},
96  {"SGD", "$"},
97  {"XAG", "Ag"},
98  {"XAU", "Au"},
99  {CNH, "¥"},
100  {"CNY", "¥"},
101  {"CZK", "Kč"},
102  {"DKK", "kr"},
103  {"HUF", "Ft"},
104  {"INR", "₹"},
105  {"MXN", "$"},
106  {"NOK", "kr"},
107  {"PLN", "zł"},
108  {"SAR", "﷼"},
109  {"SEK", "kr"},
110  {"THB", "฿"},
111  {"TRY", "₺"},
112  {"TWD", "NT$"},
113  {"ZAR", "R"},
114  {"RUB", "₽"},
115  {"BRL", "R$"},
116  {"GNF", "Fr"},
117  {IDR, "Rp"},
118 
119  {"BTC", "₿"},
120  {"BCH", "Ƀ"},
121  {"BSV", "Ɓ"},
122  {"LTC", "Ł"},
123  {"ETH", "Ξ"},
124  {"EOS", "ε"},
125  {"XRP", "✕"},
126  {"XLM", "*"},
127  {"ETC", "ξ"},
128  {"ZRX", "ZRX"},
129  {"USDT", "₮"},
130  {"ADA", "₳"},
131  {"SOL", "◎"},
132  {"DOT", "●"},
133  {"DOGE", "Ð"},
134  {"DAI", "◈"},
135  {"ALGO", "Ⱥ"},
136  {"ICP", "∞"},
137  {"XMR", "ɱ"},
138  {"XTZ", "ꜩ"},
139  {"IOTA", "ɨ"},
140  {"MIOTA", "ɨ"},
141  {"MKR", "Μ"},
142  {"ZEC", "ⓩ"},
143  {"DASH", "Đ"},
144  {"XNO", "Ӿ"},
145  {"REP", "Ɍ"},
146  {"STEEM", "ȿ"},
147  {"THETA", "ϑ"},
148  {"FIL", "⨎"},
149  {"BAT", "⟁"},
150  {"LSK", "Ⱡ"},
151  {"NAV", "Ꞥ"}
152  };
153 
154  /// <summary>
155  /// Stable pairs in GDAX. We defined them because they have different fees in GDAX market
156  /// </summary>
157  [Obsolete("StablePairsGDAX is deprecated. Use StablePairsCoinbase instead.")]
158  public static readonly HashSet<string> StablePairsGDAX = StablePairsCoinbase;
159 
160  /// <summary>
161  /// Stable pairs in Coinbase. We defined them because they have different fees in Coinbase market
162  /// </summary>
163  public static readonly HashSet<string> StablePairsCoinbase = new()
164  {
165  "DAIUSDC",
166  "DAIUSD",
167  "GYENUSD",
168  "PAXUSD",
169  "PAXUSDT",
170  "MUSDUSD",
171  "USDCEUR",
172  "USDCGBP",
173  "USDTEUR",
174  "USDTGBP",
175  "USDTUSD",
176  "USDTUSDC",
177  "USTEUR",
178  "USTUSD",
179  "USTUSDT",
180  "WBTCBTC"
181  };
182 
183  /// <summary>
184  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Coinbase market
185  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
186  ///
187  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
188  /// security.
189  /// </summary>
190  private static readonly HashSet<string> _stableCoinsWithoutPairsCoinbase = new HashSet<string>
191  {
192  "USDCUSD"
193  };
194 
195  /// <summary>
196  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
197  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
198  ///
199  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
200  /// security.
201  /// </summary>
202  private static readonly HashSet<string> _stableCoinsWithoutPairsBinance = new HashSet<string>
203  {
204  "USDCUSD",
205  "USDTUSD",
206  "USDPUSD",
207  "SUSDUSD",
208  "BUSDUSD",
209  "USTUSD",
210  "TUSDUSD",
211  "FDUSDUSD",
212  "DAIUSD",
213  "IDRTIDR"
214  };
215 
216  /// <summary>
217  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Bitfinex market
218  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
219  ///
220  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
221  /// security.
222  /// </summary>
223  private static readonly HashSet<string> _stableCoinsWithoutPairsBitfinex = new HashSet<string>
224  {
225  "EURSEUR",
226  "XCHFCHF"
227  };
228 
229  /// <summary>
230  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
231  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
232  ///
233  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
234  /// security.
235  /// </summary>
236  private static readonly HashSet<string> _stableCoinsWithoutPairsBybit = new HashSet<string>
237  {
238  "USDCUSD",
239  "USDTUSD",
240  "USDPUSD",
241  "SUSDUSD",
242  "BUSDUSD",
243  "USTUSD",
244  "TUSDUSD",
245  "DAIUSD"
246  };
247 
248  /// <summary>
249  /// Dictionary to save StableCoins in different Markets
250  /// </summary>
251  private static readonly Dictionary<string, HashSet<string>> _stableCoinsWithoutPairsMarkets = new Dictionary<string, HashSet<string>>
252  {
253  { Market.Binance , _stableCoinsWithoutPairsBinance},
254  { Market.Bitfinex , _stableCoinsWithoutPairsBitfinex},
255  { Market.Coinbase, _stableCoinsWithoutPairsCoinbase},
256  { Market.Bybit , _stableCoinsWithoutPairsBybit},
257  };
258 
259  /// <summary>
260  /// Checks whether or not certain symbol is a StableCoin without pair in a given market
261  /// </summary>
262  /// <param name="symbol">The Symbol from wich we want to know if it's a StableCoin without pair</param>
263  /// <param name="market">The market in which we want to search for that StableCoin</param>
264  /// <returns>True if the given symbol is a StableCoin without pair in the given market</returns>
265  public static bool IsStableCoinWithoutPair(string symbol, string market)
266  {
267  if (_stableCoinsWithoutPairsMarkets.TryGetValue(market, out var stableCoins) && stableCoins.Contains(symbol))
268  {
269  return true;
270  }
271  return false;
272  }
273 
274  /// <summary>
275  /// Gets the currency symbol for the specified currency code
276  /// </summary>
277  /// <param name="currency">The currency code</param>
278  /// <returns>The currency symbol</returns>
279  public static string GetCurrencySymbol(string currency)
280  {
281  if (string.IsNullOrEmpty(currency))
282  {
283  return string.Empty;
284  }
285 
286  return CurrencySymbols.TryGetValue(currency, out var currencySymbol) ? currencySymbol : currency;
287  }
288 
289  /// <summary>
290  /// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
291  /// It throws if the value cannot be converted to a decimal number.
292  /// </summary>
293  /// <param name="value">The value with currency</param>
294  /// <returns>The decimal equivalent to the value</returns>
295  public static decimal Parse(string value)
296  {
297  decimal parsedValue;
298 
299  if (!TryParse(value, out parsedValue))
300  {
301  throw new ArgumentException(Messages.Currencies.FailedConversionToDecimal(value));
302  }
303 
304  return parsedValue;
305  }
306 
307  /// <summary>
308  /// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
309  /// </summary>
310  /// <param name="value">The value with currency</param>
311  /// <param name="parsedValue">The decimal equivalent to the string value after conversion</param>
312  /// <returns>True if the value was succesfuly converted</returns>
313  public static bool TryParse(string value, out decimal parsedValue)
314  {
315  // Strip out the currency (any character before the first number) ignoring blank spaces since they are not supposed to be in numbers with currency
316  value = Regex.Replace(value, @"^[^\d\s-+]+", string.Empty);
317  return decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedValue);
318  }
319  }
320 }