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