/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text.RegularExpressions;
namespace QuantConnect
{
///
/// Provides commonly used currency pairs and symbols
///
public static class Currencies
{
///
/// USD (United States Dollar) currency string
///
public const string USD = "USD";
///
/// EUR (Euro) currency string
///
public const string EUR = "EUR";
///
/// GBP (British pound sterling) currency string
///
public const string GBP = "GBP";
///
/// INR (Indian rupee) currency string
///
public const string INR = "INR";
///
/// IDR (Indonesian rupiah) currency string
///
public const string IDR = "IDR";
///
/// CNH (Chinese Yuan Renminbi) currency string
///
public const string CNH = "CNH";
///
/// CHF (Swiss Franc) currency string
///
public const string CHF = "CHF";
///
/// HKD (Hong Kong dollar) currency string
///
public const string HKD = "HKD";
///
/// JPY (Japanese yen) currency string
///
public const string JPY = "JPY";
///
/// Null currency used when a real one is not required
///
public const string NullCurrency = "QCC";
///
/// A mapping of currency codes to their display symbols
///
///
/// Now used by Forex and CFD, should probably be moved out into its own class
///
public static readonly IReadOnlyDictionary CurrencySymbols = new Dictionary
{
{USD, "$"},
{GBP, "₤"},
{JPY, "¥"},
{EUR, "€"},
{"NZD", "$"},
{"AUD", "$"},
{"CAD", "$"},
{CHF, "Fr"},
{HKD, "$"},
{"SGD", "$"},
{"XAG", "Ag"},
{"XAU", "Au"},
{CNH, "¥"},
{"CNY", "¥"},
{"CZK", "Kč"},
{"DKK", "kr"},
{"HUF", "Ft"},
{"INR", "₹"},
{"MXN", "$"},
{"NOK", "kr"},
{"PLN", "zł"},
{"SAR", "﷼"},
{"SEK", "kr"},
{"THB", "฿"},
{"TRY", "₺"},
{"TWD", "NT$"},
{"ZAR", "R"},
{"RUB", "₽"},
{"BRL", "R$"},
{"GNF", "Fr"},
{IDR, "Rp"},
{"BTC", "₿"},
{"BCH", "Ƀ"},
{"BSV", "Ɓ"},
{"LTC", "Ł"},
{"ETH", "Ξ"},
{"EOS", "ε"},
{"XRP", "✕"},
{"XLM", "*"},
{"ETC", "ξ"},
{"ZRX", "ZRX"},
{"USDT", "₮"},
{"ADA", "₳"},
{"SOL", "◎"},
{"DOT", "●"},
{"DOGE", "Ð"},
{"DAI", "◈"},
{"ALGO", "Ⱥ"},
{"ICP", "∞"},
{"XMR", "ɱ"},
{"XTZ", "ꜩ"},
{"IOTA", "ɨ"},
{"MIOTA", "ɨ"},
{"MKR", "Μ"},
{"ZEC", "ⓩ"},
{"DASH", "Đ"},
{"XNO", "Ӿ"},
{"REP", "Ɍ"},
{"STEEM", "ȿ"},
{"THETA", "ϑ"},
{"FIL", "⨎"},
{"BAT", "⟁"},
{"LSK", "Ⱡ"},
{"NAV", "Ꞥ"}
};
///
/// Stable pairs in GDAX. We defined them because they have different fees in GDAX market
///
[Obsolete("StablePairsGDAX is deprecated. Use StablePairsCoinbase instead.")]
public static readonly HashSet StablePairsGDAX = StablePairsCoinbase;
///
/// Stable pairs in Coinbase. We defined them because they have different fees in Coinbase market
///
public static readonly HashSet StablePairsCoinbase = new()
{
"DAIUSDC",
"DAIUSD",
"GYENUSD",
"PAXUSD",
"PAXUSDT",
"MUSDUSD",
"USDCEUR",
"USDCGBP",
"USDTEUR",
"USDTGBP",
"USDTUSD",
"USDTUSDC",
"USTEUR",
"USTUSD",
"USTUSDT",
"WBTCBTC"
};
///
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Coinbase market
/// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
///
/// We use this to allow setting cash amounts for these stablecoins without needing a conversion
/// security.
///
private static readonly HashSet _stableCoinsWithoutPairsCoinbase = new HashSet
{
"USDCUSD"
};
///
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
/// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
///
/// We use this to allow setting cash amounts for these stablecoins without needing a conversion
/// security.
///
private static readonly HashSet _stableCoinsWithoutPairsBinance = new HashSet
{
"USDCUSD",
"USDTUSD",
"USDPUSD",
"SUSDUSD",
"BUSDUSD",
"USTUSD",
"TUSDUSD",
"FDUSDUSD",
"DAIUSD",
"IDRTIDR",
"BNFCRUSD"
};
///
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Bitfinex market
/// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
///
/// We use this to allow setting cash amounts for these stablecoins without needing a conversion
/// security.
///
private static readonly HashSet _stableCoinsWithoutPairsBitfinex = new HashSet
{
"EURSEUR",
"XCHFCHF"
};
///
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Binance market
/// This is because some CryptoExchanges do not define direct pairs with the stablecoins they offer.
///
/// We use this to allow setting cash amounts for these stablecoins without needing a conversion
/// security.
///
private static readonly HashSet _stableCoinsWithoutPairsBybit = new HashSet
{
"USDCUSD",
"USDTUSD",
"USDPUSD",
"SUSDUSD",
"BUSDUSD",
"USTUSD",
"TUSDUSD",
"DAIUSD"
};
///
/// Dictionary to save StableCoins in different Markets
///
private static readonly Dictionary> _stableCoinsWithoutPairsMarkets = new Dictionary>
{
{ Market.Binance , _stableCoinsWithoutPairsBinance},
{ Market.Bitfinex , _stableCoinsWithoutPairsBitfinex},
{ Market.Coinbase, _stableCoinsWithoutPairsCoinbase},
{ Market.Bybit , _stableCoinsWithoutPairsBybit},
};
///
/// Checks whether or not certain symbol is a StableCoin without pair in a given market
///
/// The Symbol from wich we want to know if it's a StableCoin without pair
/// The market in which we want to search for that StableCoin
/// True if the given symbol is a StableCoin without pair in the given market
public static bool IsStableCoinWithoutPair(string symbol, string market)
{
if (_stableCoinsWithoutPairsMarkets.TryGetValue(market, out var stableCoins) && stableCoins.Contains(symbol))
{
return true;
}
return false;
}
///
/// Gets the currency symbol for the specified currency code
///
/// The currency code
/// The currency symbol
public static string GetCurrencySymbol(string currency)
{
if (string.IsNullOrEmpty(currency))
{
return string.Empty;
}
return CurrencySymbols.TryGetValue(currency, out var currencySymbol) ? currencySymbol : currency;
}
///
/// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
/// It throws if the value cannot be converted to a decimal number.
///
/// The value with currency
/// The decimal equivalent to the value
public static decimal Parse(string value)
{
decimal parsedValue;
if (!TryParse(value, out parsedValue))
{
throw new ArgumentException(Messages.Currencies.FailedConversionToDecimal(value));
}
return parsedValue;
}
///
/// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
///
/// The value with currency
/// The decimal equivalent to the string value after conversion
/// True if the value was succesfuly converted
public static bool TryParse(string value, out decimal parsedValue)
{
// Strip out the currency (any character before the first number) ignoring blank spaces since they are not supposed to be in numbers with currency
value = Regex.Replace(value, @"^[^\d\s-+]+", string.Empty);
return decimal.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out parsedValue);
}
}
}