chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides commonly used currency pairs and symbols
|
||||
/// </summary>
|
||||
public static class Currencies
|
||||
{
|
||||
/// <summary>
|
||||
/// USD (United States Dollar) currency string
|
||||
/// </summary>
|
||||
public const string USD = "USD";
|
||||
|
||||
/// <summary>
|
||||
/// EUR (Euro) currency string
|
||||
/// </summary>
|
||||
public const string EUR = "EUR";
|
||||
|
||||
/// <summary>
|
||||
/// GBP (British pound sterling) currency string
|
||||
/// </summary>
|
||||
public const string GBP = "GBP";
|
||||
|
||||
/// <summary>
|
||||
/// INR (Indian rupee) currency string
|
||||
/// </summary>
|
||||
public const string INR = "INR";
|
||||
|
||||
/// <summary>
|
||||
/// IDR (Indonesian rupiah) currency string
|
||||
/// </summary>
|
||||
public const string IDR = "IDR";
|
||||
|
||||
/// <summary>
|
||||
/// CNH (Chinese Yuan Renminbi) currency string
|
||||
/// </summary>
|
||||
public const string CNH = "CNH";
|
||||
|
||||
/// <summary>
|
||||
/// CHF (Swiss Franc) currency string
|
||||
/// </summary>
|
||||
public const string CHF = "CHF";
|
||||
|
||||
/// <summary>
|
||||
/// HKD (Hong Kong dollar) currency string
|
||||
/// </summary>
|
||||
public const string HKD = "HKD";
|
||||
|
||||
/// <summary>
|
||||
/// JPY (Japanese yen) currency string
|
||||
/// </summary>
|
||||
public const string JPY = "JPY";
|
||||
|
||||
/// <summary>
|
||||
/// Null currency used when a real one is not required
|
||||
/// </summary>
|
||||
public const string NullCurrency = "QCC";
|
||||
|
||||
/// <summary>
|
||||
/// A mapping of currency codes to their display symbols
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Now used by Forex and CFD, should probably be moved out into its own class
|
||||
/// </remarks>
|
||||
public static readonly IReadOnlyDictionary<string, string> CurrencySymbols = new Dictionary<string, string>
|
||||
{
|
||||
{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", "Ꞥ"}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Stable pairs in GDAX. We defined them because they have different fees in GDAX market
|
||||
/// </summary>
|
||||
[Obsolete("StablePairsGDAX is deprecated. Use StablePairsCoinbase instead.")]
|
||||
public static readonly HashSet<string> StablePairsGDAX = StablePairsCoinbase;
|
||||
|
||||
/// <summary>
|
||||
/// Stable pairs in Coinbase. We defined them because they have different fees in Coinbase market
|
||||
/// </summary>
|
||||
public static readonly HashSet<string> StablePairsCoinbase = new()
|
||||
{
|
||||
"DAIUSDC",
|
||||
"DAIUSD",
|
||||
"GYENUSD",
|
||||
"PAXUSD",
|
||||
"PAXUSDT",
|
||||
"MUSDUSD",
|
||||
"USDCEUR",
|
||||
"USDCGBP",
|
||||
"USDTEUR",
|
||||
"USDTGBP",
|
||||
"USDTUSD",
|
||||
"USDTUSDC",
|
||||
"USTEUR",
|
||||
"USTUSD",
|
||||
"USTUSDT",
|
||||
"WBTCBTC"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _stableCoinsWithoutPairsCoinbase = new HashSet<string>
|
||||
{
|
||||
"USDCUSD"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _stableCoinsWithoutPairsBinance = new HashSet<string>
|
||||
{
|
||||
"USDCUSD",
|
||||
"USDTUSD",
|
||||
"USDPUSD",
|
||||
"SUSDUSD",
|
||||
"BUSDUSD",
|
||||
"USTUSD",
|
||||
"TUSDUSD",
|
||||
"FDUSDUSD",
|
||||
"DAIUSD",
|
||||
"IDRTIDR",
|
||||
"BNFCRUSD"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _stableCoinsWithoutPairsBitfinex = new HashSet<string>
|
||||
{
|
||||
"EURSEUR",
|
||||
"XCHFCHF"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in Bybit 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.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _stableCoinsWithoutPairsBybit = new HashSet<string>
|
||||
{
|
||||
"USDCUSD",
|
||||
"USDTUSD",
|
||||
"USDPUSD",
|
||||
"SUSDUSD",
|
||||
"BUSDUSD",
|
||||
"USTUSD",
|
||||
"TUSDUSD",
|
||||
"DAIUSD"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Define some StableCoins that don't have direct pairs for base currencies in our SPDB in dYdX 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.
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> _stableCoinsWithoutPairsdYdX = new HashSet<string>
|
||||
{
|
||||
"USDCUSD"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to save StableCoins in different Markets
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, HashSet<string>> _stableCoinsWithoutPairsMarkets = new Dictionary<string, HashSet<string>>
|
||||
{
|
||||
{ Market.Binance , _stableCoinsWithoutPairsBinance},
|
||||
{ Market.Bitfinex , _stableCoinsWithoutPairsBitfinex},
|
||||
{ Market.Coinbase, _stableCoinsWithoutPairsCoinbase},
|
||||
{ Market.Bybit , _stableCoinsWithoutPairsBybit},
|
||||
{ Market.DYDX , _stableCoinsWithoutPairsdYdX}
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> _dollarStablePairs = ["USDT", "USDC", USD];
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not certain symbol is a StableCoin without pair in a given market
|
||||
/// </summary>
|
||||
/// <param name="accountCurrency">The account currency</param>
|
||||
/// <param name="cashSymbol">The target cash symbol</param>
|
||||
/// <param name="market">The market in which we want to search for that StableCoin</param>
|
||||
/// <returns>True if the given symbol is a StableCoin without pair in the given market</returns>
|
||||
public static bool IsStableCoinWithoutPair(string accountCurrency, string cashSymbol, string market)
|
||||
{
|
||||
IEnumerable<string> _targets;
|
||||
if (_dollarStablePairs.Contains(accountCurrency))
|
||||
{
|
||||
// let's be polite and handle USDT/USDC/USD, this is internal
|
||||
_targets = _dollarStablePairs.Where(x => x != cashSymbol).SelectMany(x => new[] { x + cashSymbol, cashSymbol + x }).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
_targets = [accountCurrency + cashSymbol, cashSymbol + accountCurrency];
|
||||
}
|
||||
|
||||
foreach (var target in _targets)
|
||||
{
|
||||
if (IsStableCoinWithoutPair(target, market))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether or not certain symbol is a StableCoin without pair in a given market
|
||||
/// </summary>
|
||||
/// <param name="symbol">The Symbol from wich we want to know if it's a StableCoin without pair</param>
|
||||
/// <param name="market">The market in which we want to search for that StableCoin</param>
|
||||
/// <returns>True if the given symbol is a StableCoin without pair in the given market</returns>
|
||||
public static bool IsStableCoinWithoutPair(string symbol, string market)
|
||||
{
|
||||
if (_stableCoinsWithoutPairsMarkets.TryGetValue(market, out var stableCoins) && stableCoins.Contains(symbol))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the currency symbol for the specified currency code
|
||||
/// </summary>
|
||||
/// <param name="currency">The currency code</param>
|
||||
/// <returns>The currency symbol</returns>
|
||||
public static string GetCurrencySymbol(string currency)
|
||||
{
|
||||
if (string.IsNullOrEmpty(currency))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return CurrencySymbols.TryGetValue(currency, out var currencySymbol) ? currencySymbol : currency;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="value">The value with currency</param>
|
||||
/// <returns>The decimal equivalent to the value</returns>
|
||||
public static decimal Parse(string value)
|
||||
{
|
||||
decimal parsedValue;
|
||||
|
||||
if (!TryParse(value, out parsedValue))
|
||||
{
|
||||
throw new ArgumentException(Messages.Currencies.FailedConversionToDecimal(value));
|
||||
}
|
||||
|
||||
return parsedValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string representation of number with currency in the format {currency}{value} to its decimal equivalent.
|
||||
/// </summary>
|
||||
/// <param name="value">The value with currency</param>
|
||||
/// <param name="parsedValue">The decimal equivalent to the string value after conversion</param>
|
||||
/// <returns>True if the value was succesfuly converted</returns>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user