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  /// </summary>
185  private static readonly HashSet<string> _stableCoinsWithoutPairsCoinbase = new HashSet<string>
186  {
187  "USDCUSD"
188  };
189 
190  /// <summary>
191  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
192  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
193  ///
194  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
195  /// security.
196  /// </summary>
197  private static readonly HashSet<string> _stableCoinsWithoutPairsBinance = new HashSet<string>
198  {
199  "USDCUSD",
200  "USDTUSD",
201  "USDPUSD",
202  "SUSDUSD",
203  "BUSDUSD",
204  "USTUSD",
205  "TUSDUSD",
206  "FDUSDUSD",
207  "DAIUSD",
208  "IDRTIDR"
209  };
210 
211  /// <summary>
212  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Bitfinex market
213  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
214  ///
215  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
216  /// security.
217  /// </summary>
218  private static readonly HashSet<string> _stableCoinsWithoutPairsBitfinex = new HashSet<string>
219  {
220  "EURSEUR",
221  "XCHFCHF"
222  };
223 
224  /// <summary>
225  /// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
226  /// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
227  ///
228  /// We use this to allow setting cash amounts for these stablecoins without needing a conversion
229  /// security.
230  /// </summary>
231  private static readonly HashSet<string> _stableCoinsWithoutPairsBybit = new HashSet<string>
232  {
233  "USDCUSD",
234  "USDTUSD",
235  "USDPUSD",
236  "SUSDUSD",
237  "BUSDUSD",
238  "USTUSD",
239  "TUSDUSD",
240  "DAIUSD"
241  };
242 
243  /// <summary>
244  /// Dictionary to save StableCoins in different Markets
245  /// </summary>
246  private static readonly Dictionary<string, HashSet<string>> _stableCoinsWithoutPairsMarkets = new Dictionary<string, HashSet<string>>
247  {
248  { Market.Binance , _stableCoinsWithoutPairsBinance},
249  { Market.Bitfinex , _stableCoinsWithoutPairsBitfinex},
250  { Market.Coinbase, _stableCoinsWithoutPairsCoinbase},
251  { Market.Bybit , _stableCoinsWithoutPairsBybit},
252  };
253 
254  /// <summary>
255  /// Checks whether or not certain symbol is a StableCoin without pair in a given market
256  /// </summary>
257  /// <param name="symbol">The Symbol from wich we want to know if it's a StableCoin without pair</param>
258  /// <param name="market">The market in which we want to search for that StableCoin</param>
259  /// <returns>True if the given symbol is a StableCoin without pair in the given market</returns>
260  public static bool IsStableCoinWithoutPair(string symbol, string market)
261  {
262  if (_stableCoinsWithoutPairsMarkets.TryGetValue(market, out var stableCoins) && stableCoins.Contains(symbol))
263  {
264  return true;
265  }
266  return false;
267  }
268 
269  /// <summary>
270  /// Gets the currency symbol for the specified currency code
271  /// </summary>
272  /// <param name="currency">The currency code</param>
273  /// <returns>The currency symbol</returns>
274  public static string GetCurrencySymbol(string currency)
275  {
276  if (string.IsNullOrEmpty(currency))
277  {
278  return string.Empty;
279  }
280 
281  return CurrencySymbols.TryGetValue(currency, out var currencySymbol) ? currencySymbol : currency;
282  }
283 
284  /// <summary>
285  /// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
286  /// It throws if the value cannot be converted to a decimal number.
287  /// </summary>
288  /// <param name="value">The value with currency</param>
289  /// <returns>The decimal equivalent to the value</returns>
290  public static decimal Parse(string value)
291  {
292  decimal parsedValue;
293 
294  if (!TryParse(value, out parsedValue))
295  {
296  throw new ArgumentException(Messages.Currencies.FailedConversionToDecimal(value));
297  }
298 
299  return parsedValue;
300  }
301 
302  /// <summary>
303  /// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
304  /// </summary>
305  /// <param name="value">The value with currency</param>
306  /// <param name="parsedValue">The decimal equivalent to the string value after conversion</param>
307  /// <returns>True if the value was succesfuly converted</returns>
308  public static bool TryParse(string value, out decimal parsedValue)
309  {
310  // Strip out the currency (any character before the first number) ignoring blank spaces since they are not supposed to be in numbers with currency
311  value = Regex.Replace(value, @"^[^\d\s-+]+", string.Empty);
312  return decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedValue);
313  }
314  }
315 }