private void ProcessOrdersMarkedToRefund(TransactionRecordList aCurrencyTxs, ICurrencyIdentity aCurrencyItem) { if (!aCurrencyTxs.Any()) { return; } var lExchangeminConf = FExchanger.GetConfirmations(aCurrencyItem); var lCurrencyBlockHeight = FPandorasWalletConnection.GetBlockHeight(aCurrencyItem.Id); if (lExchangeminConf < 0 || lCurrencyBlockHeight <= 0) { return; } foreach (var lOrder in FWaitingToRefund.Values) { var lTx = aCurrencyTxs.ToList().Find(lTxItem => lTxItem.TxId == lOrder.CoinTxID); bool lConfirmed = lTx.Block != 0 && (lCurrencyBlockHeight - lTx.Block) > lExchangeminConf; if (lTx != null && lConfirmed) { RefundOrder(lOrder); while (!FWaitingToRefund.TryRemove(lOrder.InternalID, out UserTradeOrder lDummy)) { ; } } } }
public decimal GetTransactionsFee(ICurrencyIdentity aCurrency) { if (!FCurrencyFees.ContainsKey(aCurrency.Ticker)) { GetCurrencyRelatedData(); } return(FCurrencyFees[aCurrency.Ticker]); }
public int GetConfirmations(ICurrencyIdentity aCurrency) { if (!FConfirmations.TryGetValue(aCurrency.Ticker, out int lConfirmations)) { lConfirmations = 6; } return(lConfirmations); }
public int GetConfirmations(ICurrencyIdentity aCurrency) { if (!FCurrencyConfirmations.ContainsKey(aCurrency.Ticker)) { GetCurrencyRelatedData(); } if (!FCurrencyConfirmations.ContainsKey(aCurrency.Ticker)) { return(-1); } return(FCurrencyConfirmations[aCurrency.Ticker]); }
public BittrexExchangeMarket(BittrexExchange aExchangeInstance, ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction, BittrexSymbol aMarketPair) : base(aExchangeInstance) { SellingCurrencyInfo = aCurrency; BuyingCurrencyInfo = new CurrencyInfo(aGetWalletIDFunction) { Ticker = aMarketPair.BaseCurrency == aCurrency.Ticker ? aMarketPair.QuoteCurrency : aMarketPair.BaseCurrency, Name = aMarketPair.BaseCurrency == aCurrency.Ticker ? aMarketPair.QuoteCurrency : aMarketPair.BaseCurrency, Id = aGetWalletIDFunction?.Invoke(aMarketPair.BaseCurrency == aCurrency.Ticker ? aMarketPair.QuoteCurrency : aMarketPair.BaseCurrency) ?? 0 }; MarketPairID = aMarketPair.Symbol; MarketBaseCurrencyInfo = string.Equals(aMarketPair.BaseCurrency, aCurrency.Ticker, StringComparison.OrdinalIgnoreCase) ? BuyingCurrencyInfo : SellingCurrencyInfo; MinimumTrade = aMarketPair.MinTradeSize; }
public IEnumerable <IExchangeMarket> GetMarketCoins(ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction) { DoUpdateMarketCoins().Wait(); if (!FLocalCacheOfMarkets.TryGetValue(aCurrency.Id, out IEnumerable <PoloniexExchangeMarket> lCoinMarkets)) { lCoinMarkets = FCacheMarkets.Where(lPair => lPair.Key.EndsWith($"_{aCurrency.Ticker}") || lPair.Key.StartsWith($"{aCurrency.Ticker}_")) .Select(lPair => new PoloniexExchangeMarket(this, aCurrency, aGetWalletIDFunction, lPair.Key)); if (aGetWalletIDFunction != null) { FLocalCacheOfMarkets.TryAdd(aCurrency.Id, lCoinMarkets); } } return(lCoinMarkets); }
public IEnumerable <IExchangeMarket> GetMarketCoins(ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction) { DoUpdatemarketCoins().Wait(); if (!FLocalCacheOfMarkets.TryGetValue(aCurrency.Id, out IEnumerable <BitfinexExchangeMarket> lCoinMarkets)) { var lMarketsWithCompleteData = FMarkets.Where(lMarket => lMarket?.BaseCurrency?.FullName != null && lMarket?.DestinationCurrency?.FullName != null); lCoinMarkets = lMarketsWithCompleteData.Where(lMarket => string.Equals(lMarket.DestinationCurrency.FullName, aCurrency.Name, StringComparison.OrdinalIgnoreCase) || string.Equals(lMarket.BaseCurrency.FullName, aCurrency.Name, StringComparison.OrdinalIgnoreCase)) .Select(lMarket => new BitfinexExchangeMarket(this, aCurrency, aGetWalletIDFunction, lMarket)); if (aGetWalletIDFunction != null) { FLocalCacheOfMarkets.TryAdd(aCurrency.Id, lCoinMarkets); } } return(lCoinMarkets); }
public IEnumerable <IExchangeMarket> GetMarketCoins(ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction) { DoUpdateMarketCoins().Wait(); if (!FLocalCacheOfMarkets.TryGetValue(aCurrency.Id, out IEnumerable <BittrexExchangeMarket> lCoinMarkets)) { lCoinMarkets = FMarkets.Where(x => x.Status == SymbolStatus.Online && (x.QuoteCurrency == aCurrency.Ticker || x.BaseCurrency == aCurrency.Ticker)) .Select(lMarket => new BittrexExchangeMarket(this, aCurrency, aGetWalletIDFunction, lMarket)).ToArray(); if (aGetWalletIDFunction != null) { FLocalCacheOfMarkets.TryAdd(aCurrency.Id, lCoinMarkets); } } return(lCoinMarkets); }
public PoloniexExchangeMarket(PoloniexExchange aExchangeInstance, ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction, string aPairName) : base(aExchangeInstance) { MarketPairID = string.IsNullOrEmpty(aPairName) ? throw new ArgumentException("Poloniex pair name can not be null or empty") : aPairName; var lPoloniexBuyingTicker = GetPairTicker(aPairName, aCurrency.Ticker, out bool lIsBase); var lPoloniexBuyingName = aExchangeInstance.GetPoloniexCurrency(lPoloniexBuyingTicker)?.name ?? throw new Exception("market currency pair info not found"); SellingCurrencyInfo = aCurrency; BuyingCurrencyInfo = new CurrencyInfo(aGetWalletIDFunction) { Ticker = lPoloniexBuyingTicker, Name = lPoloniexBuyingName, Id = aGetWalletIDFunction?.Invoke(lPoloniexBuyingTicker) ?? 0 }; MarketBaseCurrencyInfo = lIsBase ? BuyingCurrencyInfo : SellingCurrencyInfo; MinimumTrade = 0.0001M; //This info I found it at the web }
public BitfinexExchangeMarket(BitfinexExchange aExchangeInstance, ICurrencyIdentity aCurrency, GetWalletIDDelegate aGetWalletIDFunction, BitfinexPair aPair) : base(aExchangeInstance) { var lIsBaseCurrency = string.Equals(aPair.BaseCurrency.FullName, aCurrency.Name, StringComparison.OrdinalIgnoreCase); SellingCurrencyInfo = aCurrency; var lBuyingCurrencyTicker = lIsBaseCurrency ? aPair.DestinationCurrency.Name : aPair.BaseCurrency.Name; BuyingCurrencyInfo = new CurrencyInfo(aGetWalletIDFunction) { Ticker = lBuyingCurrencyTicker, Name = lIsBaseCurrency ? aPair.DestinationCurrency.FullName : aPair.BaseCurrency.FullName, Id = aGetWalletIDFunction?.Invoke(lBuyingCurrencyTicker) ?? 0 }; MarketPairID = aPair.MarketDetails.Pair; MarketBaseCurrencyInfo = lIsBaseCurrency ? SellingCurrencyInfo : BuyingCurrencyInfo; MinimumTrade = aPair.MarketDetails?.MinimumOrderSize ?? 0; }
public decimal GetTransactionsFee(ICurrencyIdentity aCurrency) { decimal?lResult = null; if (FLastFeesDataRetrieval == DateTime.MinValue || FLastFeesDataRetrieval < DateTime.UtcNow.AddDays(-1)) { using (var lClient = new BitfinexClient()) { var lResponse = lClient.GetWithdrawalFeesAsync().Result; if (!lResponse.Success) { throw new Exception($"Failed to get withdrawn fees from exchange server. {lResponse.Error}"); } var lFees = lResponse.Data.Withdraw; FWithdrawnFeesCache.Clear(); foreach (var lFee in lFees) { FWithdrawnFeesCache.TryAdd(lFee.Key, lFee.Value); } } FLastFeesDataRetrieval = DateTime.UtcNow; } if (FWithdrawnFeesCache.TryGetValue(aCurrency.Ticker, out decimal lTxFee)) { lResult = lTxFee; } else { using (var lClient = new BitfinexClient()) { var lResponse = lClient.GetCurrenciesAsync().Result; if (lResponse.Success) { var lExchangeTicker = lResponse.Data.Where(lCurrency => string.Equals(lCurrency.FullName, aCurrency.Name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault()?.Name; if (lExchangeTicker != null && FWithdrawnFeesCache.TryGetValue(lExchangeTicker, out lTxFee)) { lResult = lTxFee; } } } } return(lResult ?? throw new Exception($"Transaction fee for currency with ticker '{aCurrency.Ticker}' not found")); }
/// <summary> /// Checks order that are in waiting state, and changes it to placed state if is needed (Here transaction confirmations are verified)) /// </summary> /// <param name="aWaitingOrders">Orders with waiting state</param> /// <param name="aCurrencyItem">Order currency item</param> /// <param name="aCurrencyTransactions">Pandora's currency transactions</param> /// <param name="aListExchangeCoinMarket">Markets to look for</param> private void VerifyWaitingOrders(IEnumerable <UserTradeOrder> aWaitingOrders, ICurrencyIdentity aCurrencyItem, IEnumerable <TransactionRecord> aCurrencyTransactions) { long lCurrencyBlockHeight; int lExchangeminConf; ScanForCancelledOrders(aWaitingOrders); if (!aWaitingOrders.Any() || !aCurrencyTransactions.Any() || (lExchangeminConf = FExchanger.GetConfirmations(aCurrencyItem)) < 0 || (lCurrencyBlockHeight = FPandorasWalletConnection.GetBlockHeight(aCurrencyItem.Id)) <= 0) { return; } var lConfirmedTxs = aCurrencyTransactions.Where(lTx => lTx.Block != 0 && (lCurrencyBlockHeight - lTx.Block) > lExchangeminConf); foreach (var lTx in lConfirmedTxs) { UserTradeOrder lItem = aWaitingOrders.Where(lOrder => lOrder.CoinTxID == lTx.TxId).FirstOrDefault(); if (lItem == null) { continue; } if (lItem.Status == OrderStatus.Waiting && lItem.Market != null) { TryToPlaceOrder(lItem); } } }
public int GetConfirmations(ICurrencyIdentity aCurrency) { return(GetPoloniexCurrency(aCurrency.Ticker).minConf); }
/// <summary> /// Loads currency exchange orders from disk. This should only be called once or to reload orders. /// </summary> /// <param name="aCurrencyTicker"></param> /// <param name="aCurrencyID"></param> /// <returns></returns> public IEnumerable <UserTradeOrder> LoadOrders(ICurrencyIdentity aCurrency, IPandoraExchangeFactory lExchangeFactory, GetWalletIDDelegate aGetWalletIDFunction) { var lResult = new List <UserTradeOrder>(); var lDBOrders = FSaveManager.ReadOrders(aCurrency); if (lDBOrders != null && lDBOrders.Any()) { int lErrorCounter; var lMarketCache = new Dictionary <int, IEnumerable <IExchangeMarket> >(); foreach (var lDBOrder in lDBOrders) { bool lOrdersLogs = FSaveManager.ReadOrderLogs(lDBOrder.InternalID, out List <OrderMessage> lMessages); lMessages = lMessages.OrderBy(lMessage => lMessage.Time).ToList(); lErrorCounter = 0; for (int it2 = 0; it2 < lMessages.Count; it2++) { OrderMessage lIndividualMessage = lMessages[it2]; switch (lIndividualMessage.Level) { case OrderMessage.OrderMessageLevel.Error: lErrorCounter += 60; break; case OrderMessage.OrderMessageLevel.StageChange: lErrorCounter = 0; break; case OrderMessage.OrderMessageLevel.FatalError: lErrorCounter = -1; break; } if (lErrorCounter == -1) { break; } } var lExchanger = lExchangeFactory.GetPandoraExchange((AvailableExchangesList)lDBOrder.ExchangeID); if (!lMarketCache.TryGetValue(lDBOrder.ExchangeID, out IEnumerable <IExchangeMarket> lMarkets)) { lMarkets = lExchanger.GetMarketCoins(aCurrency, aGetWalletIDFunction); lMarketCache.Add(lDBOrder.ExchangeID, lMarkets); } var lUserOrder = new UserTradeOrder { InternalID = lDBOrder.InternalID, ID = lDBOrder.ID, Name = lDBOrder.Name, SentQuantity = lDBOrder.SentQuantity, Status = lDBOrder.Status, CoinTxID = lDBOrder.CoinTxID, StopPrice = lDBOrder.StopPrice, OpenTime = lDBOrder.OpenTime, Rate = lDBOrder.Rate, ProfileID = lDBOrder.ProfileID, ErrorCounter = lErrorCounter, Completed = lDBOrder.Completed, Cancelled = lDBOrder.Cancelled, Market = lMarkets.FindByMarketID(lDBOrder.MarketID) }; if (lUserOrder.Market == null) { Log.Write(LogLevel.Warning, $"Exchange: Unable to find market for order of id {lUserOrder.InternalID} of exchange {lExchanger.Name}"); continue; } lResult.Add(lUserOrder); SetOrderInCache(lUserOrder, lDBOrder.ExchangeID); } } return(lResult); }
public IEnumerable <DBUserTradeOrder> ReadOrders(ICurrencyIdentity aCurrency = null, int?aExchangeID = null) { if (!Initialized) { throw new Exception("Save manager not initialized"); } string lQry = "SELECT A.InternalID, A.ID, A.Market, A.Quantity, A.OpenTime, A.Rate, A.Completed, A.Cancelled, A.Status, A.CoinTxID, A.CurrencyTicker, A.CurrencyId, A.Name, A.Stop, A.ProfileID, B.ExchangeID FROM ExchangeTx A " + "inner join Relationship_ExchangeID_OrderID B ON A.InternalID = B.InternalOrderID WHERE 1"; if (aCurrency != null) { lQry += $" AND ( A.CurrencyId = {aCurrency.Id} OR A.CurrencyTicker = '{aCurrency.Ticker}')"; } if (aExchangeID.HasValue) { lQry += $" AND B.ExchangeID = {aExchangeID}"; } var lListOrders = new List <DBUserTradeOrder>(); using (SQLiteConnection lConnection = new SQLiteConnection(FConnectionString)) using (SQLiteCommand command = new SQLiteCommand(lQry, lConnection)) { try { lConnection.Open(); using (SQLiteDataReader rdr = command.ExecuteReader()) { while (rdr.Read()) { decimal lRate = rdr.GetDecimal(5); decimal lStop = rdr.GetDecimal(13); DBUserTradeOrder lOrder = new DBUserTradeOrder { InternalID = rdr.GetInt32(0), ID = rdr[1] as string, MarketID = rdr.GetString(2), SentQuantity = rdr.GetDecimal(3), OpenTime = rdr.GetDateTime(4), Rate = lRate, Completed = rdr.GetBoolean(6), Cancelled = rdr.GetBoolean(7), Status = (OrderStatus)rdr.GetInt32(8), CoinTxID = rdr.GetString(9), CurrencyTicker = rdr.GetString(10), CurrencyId = rdr.IsDBNull(11) ? 0 : rdr.GetInt64(11), Name = rdr.GetString(12), StopPrice = lStop == 0 ? lRate : lStop, ProfileID = rdr.GetInt32(14), ExchangeID = rdr.GetInt32(15), }; lListOrders.Add(lOrder); } } return(lListOrders); } catch (Exception ex) { Universal.Log.Write(Universal.LogLevel.Error, $"Error reading enchange orders from db. Exception {ex}"); throw; } finally { lConnection.Close(); } } }
/// <summary> /// Checks order that are in initial state, and changes it to waiting state if is needed (Here the stop price is verified) /// </summary> /// <param name="aInitialOrders">Orders with initial state</param> /// <param name="aTicker">Order currency ticker</param> /// <param name="aCurrencyID">Order currency id</param> private void VerifyInitialOrders(IEnumerable <UserTradeOrder> aInitialOrders, ICurrencyIdentity aCurrency) { ScanForCancelledOrders(aInitialOrders); if (!aInitialOrders.Any()) { return; } foreach (UserTradeOrder lOrder in aInitialOrders) { bool lPlaceOrderFlag; if (lOrder.Market.MarketDirection == MarketDirection.Sell) { lPlaceOrderFlag = lOrder.StopPrice <= lOrder.Market.Prices.Bid; } else { lPlaceOrderFlag = lOrder.StopPrice >= lOrder.Market.Prices.Ask; } if (lPlaceOrderFlag) { TryToTransferMoneyToExchange(lOrder); } } }
public decimal GetTransactionsFee(ICurrencyIdentity aCurrency) { return(GetPoloniexCurrency(aCurrency.Ticker).txFee); }