private ExchangeRate CreateExchangeRate(KeyValuePair <string, ExchangeTicker> ticker) { if (notFoundSymbols.Contains(ticker.Key)) { return(null); } try { var tickerName = _ExchangeAPI.ExchangeSymbolToGlobalSymbol(ticker.Key); if (!CurrencyPair.TryParse(tickerName, out var pair)) { notFoundSymbols.Add(ticker.Key); return(null); } if (ReverseCurrencyPair) { pair = new CurrencyPair(pair.Right, pair.Left); } var rate = new ExchangeRate(); rate.CurrencyPair = pair; rate.Exchange = _ExchangeName; rate.BidAsk = new BidAsk(ticker.Value.Bid, ticker.Value.Ask); return(rate); } catch (ArgumentException) { notFoundSymbols.Add(ticker.Key); return(null); } }
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { var exchangeName = node.Expression.ToString(); if (exchangeName.StartsWith("ERR_", StringComparison.OrdinalIgnoreCase)) { Errors.Add(RateRulesErrors.PreprocessError); return(base.VisitInvocationExpression(node)); } var currencyPair = node.ArgumentList.ChildNodes().FirstOrDefault()?.ToString(); if (currencyPair == null || !CurrencyPair.TryParse(currencyPair, out var pair)) { Errors.Add(RateRulesErrors.InvalidCurrencyIdentifier); return(RateRules.CreateExpression($"ERR_INVALID_CURRENCY_PAIR({node.ToString()})")); } else { var rate = Rates.GetRate(exchangeName, pair); if (rate == null) { Errors.Add(RateRulesErrors.RateUnavailable); return(RateRules.CreateExpression($"ERR_RATE_UNAVAILABLE({exchangeName}, {pair.ToString()})")); } else { return(RateRules.CreateExpression(rate.ToString())); } } }
private async Task <PairRate> CreateExchangeRate(T exchangeAPI, KeyValuePair <string, ExchangeTicker> ticker) { if (notFoundSymbols.TryGetValue(ticker.Key, out _)) { return(null); } if (ticker.Key.Contains("XMR")) { } try { CurrencyPair pair; if (ticker.Value.Volume.BaseCurrency is not null && ticker.Value.Volume.QuoteCurrency is not null) { pair = new CurrencyPair(ticker.Value.Volume.BaseCurrency, ticker.Value.Volume.QuoteCurrency); } else { var tickerName = await exchangeAPI.ExchangeMarketSymbolToGlobalMarketSymbolAsync(ticker.Key); if (!CurrencyPair.TryParse(tickerName, out pair)) { notFoundSymbols.TryAdd(ticker.Key, ticker.Key); return(null); } } return(new PairRate(pair, new BidAsk(ticker.Value.Bid, ticker.Value.Ask))); }
private async Task <PairRate> CreateExchangeRate(T exchangeAPI, KeyValuePair <string, ExchangeTicker> ticker) { if (notFoundSymbols.TryGetValue(ticker.Key, out _)) { return(null); } try { var tickerName = await exchangeAPI.ExchangeMarketSymbolToGlobalMarketSymbolAsync(ticker.Key); if (!CurrencyPair.TryParse(tickerName, out var pair)) { notFoundSymbols.TryAdd(ticker.Key, ticker.Key); return(null); } if (ReverseCurrencyPair) { pair = new CurrencyPair(pair.Right, pair.Left); } return(new PairRate(pair, new BidAsk(ticker.Value.Bid, ticker.Value.Ask))); } catch (ArgumentException) { notFoundSymbols.TryAdd(ticker.Key, ticker.Key); return(null); } }
public async Task <IActionResult> GetRates2(string currencyPairs, string storeId, CancellationToken cancellationToken) { var store = CurrentStore ?? await _storeRepo.FindStore(storeId); if (store == null) { var err = Json(new BitpayErrorsModel { Error = "Store not found" }); err.StatusCode = 404; return(err); } if (currencyPairs == null) { currencyPairs = store.GetStoreBlob().GetDefaultCurrencyPairString(); if (string.IsNullOrEmpty(currencyPairs)) { var result = Json(new BitpayErrorsModel() { Error = "You need to setup the default currency pairs in 'Store Settings / Rates' or specify 'currencyPairs' query parameter (eg. BTC_USD,LTC_CAD)." }); result.StatusCode = 400; return(result); } } var rules = store.GetStoreBlob().GetRateRules(_networkProvider); var pairs = new HashSet <CurrencyPair>(); foreach (var currency in currencyPairs.Split(',')) { if (!CurrencyPair.TryParse(currency, out var pair)) { var result = Json(new BitpayErrorsModel() { Error = $"Currency pair {currency} uncorrectly formatted" }); result.StatusCode = 400; return(result); } pairs.Add(pair); } var fetching = _rateProviderFactory.FetchRates(pairs, rules, cancellationToken); await Task.WhenAll(fetching.Select(f => f.Value).ToArray()); return(Json(pairs .Select(r => (Pair: r, Value: fetching[r].GetAwaiter().GetResult().BidAsk?.Bid)) .Where(r => r.Value.HasValue) .Select(r => new Rate { CryptoCode = r.Pair.Left, Code = r.Pair.Right, CurrencyPair = r.Pair.ToString(), Name = _currencyNameTable.GetCurrencyData(r.Pair.Right, true).Name, Value = r.Value.Value }).Where(n => n.Name != null).ToArray())); }
public async Task <PairRate[]> GetRatesAsync(CancellationToken cancellationToken) { var result = new List <PairRate>(); var symbols = await GetSymbolsAsync(cancellationToken); var helper = (ExchangeKrakenAPI)await ExchangeAPI.GetExchangeAPIAsync <ExchangeKrakenAPI>(); var normalizedPairsList = symbols.Where(s => !notFoundSymbols.ContainsKey(s)).Select(s => helper.NormalizeMarketSymbol(s)).ToList(); var csvPairsList = string.Join(",", normalizedPairsList); JToken apiTickers = await MakeJsonRequestAsync <JToken>("/0/public/Ticker", null, new Dictionary <string, object> { { "pair", csvPairsList } }, cancellationToken : cancellationToken); var tickers = new List <KeyValuePair <string, ExchangeTicker> >(); foreach (string symbol in symbols) { var ticker = ConvertToExchangeTicker(symbol, apiTickers[symbol]); if (ticker != null) { try { string global = null; var mapped1 = _TickerMapping.Where(t => symbol.StartsWith(t.Key, StringComparison.OrdinalIgnoreCase)) .Select(t => new { KrakenTicker = t.Key, PayTicker = t.Value }).SingleOrDefault(); if (mapped1 != null) { var p2 = symbol.Substring(mapped1.KrakenTicker.Length); if (_TickerMapping.TryGetValue(p2, out var mapped2)) { p2 = mapped2; } global = $"{mapped1.PayTicker}_{p2}"; } else { global = await helper.ExchangeMarketSymbolToGlobalMarketSymbolAsync(symbol); } if (CurrencyPair.TryParse(global, out var pair)) { result.Add(new PairRate(pair, new BidAsk(ticker.Bid, ticker.Ask))); } else { notFoundSymbols.TryAdd(symbol, symbol); } } catch (ArgumentException) { notFoundSymbols.TryAdd(symbol, symbol); } } } return(result.ToArray()); }
public async Task <ExchangeRates> GetRatesAsync() { string url = Exchange == CoinAverageName ? $"https://apiv2.bitcoinaverage.com/indices/{Market}/ticker/short" : $"https://apiv2.bitcoinaverage.com/exchanges/{Exchange}"; var request = new HttpRequestMessage(HttpMethod.Get, url); var auth = Authenticator; if (auth != null) { await auth.AddHeader(request); } var resp = await HttpClient.SendAsync(request); using (resp) { if ((int)resp.StatusCode == 401) { throw new CoinAverageException("Unauthorized access to the API"); } if ((int)resp.StatusCode == 429) { throw new CoinAverageException("Exceed API limits"); } if ((int)resp.StatusCode == 403) { throw new CoinAverageException("Unauthorized access to the API, premium plan needed"); } resp.EnsureSuccessStatusCode(); var rates = JObject.Parse(await resp.Content.ReadAsStringAsync()); if (Exchange != CoinAverageName) { rates = (JObject)rates["symbols"]; } var exchangeRates = new ExchangeRates(); foreach (var prop in rates.Properties()) { ExchangeRate exchangeRate = new ExchangeRate(); exchangeRate.Exchange = Exchange; if (!TryToBidAsk(prop, out var value)) { continue; } exchangeRate.BidAsk = value; if (CurrencyPair.TryParse(prop.Name, out var pair)) { exchangeRate.CurrencyPair = pair; exchangeRates.Add(exchangeRate); } } return(exchangeRates); } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { try { return(reader.TokenType == JsonToken.Null ? null : CurrencyPair.TryParse((string)reader.Value, out var result) ? result : throw new JsonObjectException("Invalid currency pair", reader)); } catch (InvalidCastException) { throw new JsonObjectException("Invalid currency pair", reader); } }
private static Sensitivity ReadSensitivityFx(EntryObject o) { if (!Enum.TryParse(o.ProductClass, out Model.Product product)) { throw new InvalidDataException($"The CRIF file contains a {o.RiskType} entry with an invalid ProductClass property."); } if (product != Model.Product.RatesFx) { throw new InvalidDataException($"The CRIF file contains a {o.RiskType} entry associated to a product class other than {Model.Product.RatesFx}."); } Amount amount = ReadAmount(o); RegulationsInfo regulationsInfo = ReadRegulationsInfo(o); TradeInfo tradeInfo = ReadTradeInfo(o); if (o.RiskType == "Risk_FX") { if (!Currency.TryParse(o.Qualifier, out Currency currency)) { throw new InvalidDataException("The CRIF file contains a Risk_FX entry with an invalid Qualifier property."); } if (!String.IsNullOrEmpty(o.Bucket) || !String.IsNullOrEmpty(o.Label1) || !String.IsNullOrEmpty(o.Label2)) { throw new InvalidDataException("The CRIF file cannot specify Bucket, Label1 and Label2 properties for Risk_FX entries."); } return(Sensitivity.FxDelta(currency, amount, regulationsInfo, tradeInfo)); } if (!CurrencyPair.TryParse(o.Qualifier, out CurrencyPair pair)) { throw new InvalidDataException("The CRIF file contains a Risk_FXVol entry with an invalid Qualifier property."); } if (!Tenor.TryParse(o.Label1, out Tenor tenor)) { throw new InvalidDataException("The CRIF file contains a Risk_FXVol entry with an invalid Label1 property."); } if (!String.IsNullOrEmpty(o.Bucket) || !String.IsNullOrEmpty(o.Label2)) { throw new InvalidDataException("The CRIF file cannot specify the Label2 property for Risk_EquityVol entries."); } return(Sensitivity.FxVega(pair, tenor, amount, regulationsInfo, tradeInfo)); }
public async Task <ExchangeRates> GetRatesAsync() { var result = new ExchangeRates(); var symbols = await GetSymbolsAsync(); var normalizedPairsList = symbols.Where(s => !notFoundSymbols.ContainsKey(s)).Select(s => _Helper.NormalizeSymbol(s)).ToList(); var csvPairsList = string.Join(",", normalizedPairsList); JToken apiTickers = await MakeJsonRequestAsync <JToken>("/0/public/Ticker", null, new Dictionary <string, object> { { "pair", csvPairsList } }); var tickers = new List <KeyValuePair <string, ExchangeTicker> >(); foreach (string symbol in symbols) { var ticker = ConvertToExchangeTicker(symbol, apiTickers[symbol]); if (ticker != null) { try { string global = null; if (symbol.StartsWith("DASH", StringComparison.OrdinalIgnoreCase)) { var p2 = symbol.Substring(4); p2 = p2 == "XBT" ? "BTC" : p2; global = $"{p2}_{symbol.Substring(0, 4)}"; } else { global = _Helper.ExchangeSymbolToGlobalSymbol(symbol); } if (CurrencyPair.TryParse(global, out var pair)) { result.Add(new ExchangeRate("kraken", pair.Inverse(), new BidAsk(ticker.Bid, ticker.Ask))); } else { notFoundSymbols.TryAdd(symbol, symbol); } } catch (ArgumentException) { notFoundSymbols.TryAdd(symbol, symbol); } } } return(result); }
public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) { if ( (!IsInvocation || IsArgumentList) && CurrencyPair.TryParse(node.Identifier.ValueText, out var currentPair)) { var replacedPair = new CurrencyPair(left: currentPair.Left == "X" ? pair.Left : currentPair.Left, right: currentPair.Right == "X" ? pair.Right : currentPair.Right); if (IsInvocation) // eg. replace bittrex(BTC_X) to bittrex(BTC_USD) { ExchangeRates.Add(new ExchangeRate() { CurrencyPair = replacedPair, Exchange = _ExchangeName }); return(SyntaxFactory.IdentifierName(replacedPair.ToString())); } else // eg. replace BTC_X to BTC_USD, then replace by the expression for BTC_USD { var bestCandidate = parent.FindBestCandidate(replacedPair); if (nested > MaxNestedCount) { Errors.Add(RateRulesErrors.TooMuchNestedCalls); return(RateRules.CreateExpression($"ERR_TOO_MUCH_NESTED_CALLS({replacedPair})")); } var innerFlatten = CreateNewContext(replacedPair); var replaced = innerFlatten.Visit(bestCandidate); if (replaced is ExpressionSyntax expression) { var hasBinaryOps = new HasBinaryOperations(); hasBinaryOps.Visit(expression); if (hasBinaryOps.Result) { replaced = SyntaxFactory.ParenthesizedExpression(expression); } } if (Errors.Contains(RateRulesErrors.TooMuchNestedCalls)) { return(RateRules.CreateExpression($"ERR_TOO_MUCH_NESTED_CALLS({replacedPair})")); } return(replaced); } } return(base.VisitIdentifierName(node)); }
public async Task <IActionResult> Rates(RatesViewModel model, string command = null, string storeId = null, CancellationToken cancellationToken = default) { model.SetExchangeRates(GetSupportedExchanges(), model.PreferredExchange); model.StoreId = storeId ?? model.StoreId; CurrencyPair[] currencyPairs = null; try { currencyPairs = model.DefaultCurrencyPairs? .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(p => CurrencyPair.Parse(p)) .ToArray(); } catch { ModelState.AddModelError(nameof(model.DefaultCurrencyPairs), "Invalid currency pairs (should be for example: BTC_USD,BTC_CAD,BTC_JPY)"); } if (!ModelState.IsValid) { return(View(model)); } if (model.PreferredExchange != null) { model.PreferredExchange = model.PreferredExchange.Trim().ToLowerInvariant(); } var blob = StoreData.GetStoreBlob(); model.DefaultScript = blob.GetDefaultRateRules(_NetworkProvider).ToString(); model.AvailableExchanges = GetSupportedExchanges(); blob.PreferredExchange = model.PreferredExchange; blob.Spread = (decimal)model.Spread / 100.0m; blob.DefaultCurrencyPairs = currencyPairs; if (!model.ShowScripting) { if (!GetSupportedExchanges().Select(c => c.Name).Contains(blob.PreferredExchange, StringComparer.OrdinalIgnoreCase)) { ModelState.AddModelError(nameof(model.PreferredExchange), $"Unsupported exchange ({model.RateSource})"); return(View(model)); } } RateRules rules = null; if (model.ShowScripting) { if (!RateRules.TryParse(model.Script, out rules, out var errors)) { errors = errors ?? new List <RateRulesErrors>(); var errorString = String.Join(", ", errors.ToArray()); ModelState.AddModelError(nameof(model.Script), $"Parsing error ({errorString})"); return(View(model)); } else { blob.RateScript = rules.ToString(); ModelState.Remove(nameof(model.Script)); model.Script = blob.RateScript; } } rules = blob.GetRateRules(_NetworkProvider); if (command == "Test") { if (string.IsNullOrWhiteSpace(model.ScriptTest)) { ModelState.AddModelError(nameof(model.ScriptTest), "Fill out currency pair to test for (like BTC_USD,BTC_CAD)"); return(View(model)); } var splitted = model.ScriptTest.Split(',', StringSplitOptions.RemoveEmptyEntries); var pairs = new List <CurrencyPair>(); foreach (var pair in splitted) { if (!CurrencyPair.TryParse(pair, out var currencyPair)) { ModelState.AddModelError(nameof(model.ScriptTest), $"Invalid currency pair '{pair}' (it should be formatted like BTC_USD,BTC_CAD)"); return(View(model)); } pairs.Add(currencyPair); } var fetchs = _RateFactory.FetchRates(pairs.ToHashSet(), rules, cancellationToken); var testResults = new List <RatesViewModel.TestResultViewModel>(); foreach (var fetch in fetchs) { var testResult = await(fetch.Value); testResults.Add(new RatesViewModel.TestResultViewModel() { CurrencyPair = fetch.Key.ToString(), Error = testResult.Errors.Count != 0, Rule = testResult.Errors.Count == 0 ? testResult.Rule + " = " + testResult.BidAsk.Bid.ToString(CultureInfo.InvariantCulture) : testResult.EvaluatedRule }); } model.TestRateRules = testResults; return(View(model)); } else // command == Save { if (StoreData.SetStoreBlob(blob)) { await _Repo.UpdateStore(StoreData); StatusMessage = "Rate settings updated"; } return(RedirectToAction(nameof(Rates), new { storeId = StoreData.Id })); } }
public async Task <IActionResult> GetRates2(string currencyPairs, string storeId) { if (storeId == null || currencyPairs == null) { var result = Json(new BitpayErrorsModel() { Error = "You need to specify storeId (in your store settings) and currencyPairs (eg. BTC_USD,LTC_CAD)" }); result.StatusCode = 400; return(result); } var store = this.HttpContext.GetStoreData(); if (store == null || store.Id != storeId) { store = await _StoreRepo.FindStore(storeId); } if (store == null) { var result = Json(new BitpayErrorsModel() { Error = "Store not found" }); result.StatusCode = 404; return(result); } var rules = store.GetStoreBlob().GetRateRules(_NetworkProvider); HashSet <CurrencyPair> pairs = new HashSet <CurrencyPair>(); foreach (var currency in currencyPairs.Split(',')) { if (!CurrencyPair.TryParse(currency, out var pair)) { var result = Json(new BitpayErrorsModel() { Error = $"Currency pair {currency} uncorrectly formatted" }); result.StatusCode = 400; return(result); } pairs.Add(pair); } var fetching = _RateProviderFactory.FetchRates(pairs, rules); await Task.WhenAll(fetching.Select(f => f.Value).ToArray()); return(Json(pairs .Select(r => (Pair: r, Value: fetching[r].GetAwaiter().GetResult().Value)) .Where(r => r.Value.HasValue) .Select(r => new Rate() { CryptoCode = r.Pair.Left, Code = r.Pair.Right, CurrencyPair = r.Pair.ToString(), Name = _CurrencyNameTable.GetCurrencyData(r.Pair.Right, true).Name, Value = r.Value.Value }).Where(n => n.Name != null).ToArray())); }
public async Task <IActionResult> GetRates2(string currencyPairs, string storeId, CancellationToken cancellationToken) { storeId = await GetStoreId(storeId); if (storeId == null) { var result = Json(new BitpayErrorsModel() { Error = "Debe especificar storeId (en la configuración de su tienda)" }); result.StatusCode = 400; return(result); } var store = this.HttpContext.GetStoreData(); if (store == null || store.Id != storeId) { store = await _StoreRepo.FindStore(storeId); } if (store == null) { var result = Json(new BitpayErrorsModel() { Error = "Tienda no encontrada" }); result.StatusCode = 404; return(result); } if (currencyPairs == null) { currencyPairs = store.GetStoreBlob().GetDefaultCurrencyPairString(); if (string.IsNullOrEmpty(currencyPairs)) { var result = Json(new BitpayErrorsModel() { Error = "Debe configurar los pares de divisas predeterminados en 'Configuraciones / tarifas de la tienda' o especificar el parámetro de consulta 'currencyPairs' (por ejemplo, BTC_USD, LTC_CAD)." }); result.StatusCode = 400; return(result); } } var rules = store.GetStoreBlob().GetRateRules(_NetworkProvider); HashSet <CurrencyPair> pairs = new HashSet <CurrencyPair>(); foreach (var currency in currencyPairs.Split(',')) { if (!CurrencyPair.TryParse(currency, out var pair)) { var result = Json(new BitpayErrorsModel() { Error = $"Par de divisas {currency} formateado incorrectamente" }); result.StatusCode = 400; return(result); } pairs.Add(pair); } var fetching = _RateProviderFactory.FetchRates(pairs, rules, cancellationToken); await Task.WhenAll(fetching.Select(f => f.Value).ToArray()); return(Json(pairs .Select(r => (Pair: r, Value: fetching[r].GetAwaiter().GetResult().BidAsk?.Bid)) .Where(r => r.Value.HasValue) .Select(r => new Rate() { CryptoCode = r.Pair.Left, Code = r.Pair.Right, CurrencyPair = r.Pair.ToString(), Name = _CurrencyNameTable.GetCurrencyData(r.Pair.Right, true).Name, Value = r.Value.Value }).Where(n => n.Name != null).ToArray())); }