using Binance.Net.Clients; using Binance.Net.Objects; using Binance.TradeRobot.Model.Base; using CryptoExchange.Net.Authentication; using SDKAdapter.Model; using System; using System.Collections.Generic; using System.Linq; namespace SDKAdapter.APIClient { public class BinanceAPIClient : BaseAPIClient { private BinanceClient binanceClient; public BinanceAPIClient(long accountId, string apiKey, string secret) : base(accountId, apiKey, secret) { var spotClientOption = new BinanceApiClientOptions() { BaseAddress = "https://api.binance.com", ApiCredentials = new ApiCredentials(apiKey, secret) }; var usdFuturesClientOption = new BinanceApiClientOptions() { BaseAddress = "https://fapi.binance.com", ApiCredentials = new ApiCredentials(apiKey, secret) }; binanceClient = new BinanceClient(new BinanceClientOptions() { UsdFuturesApiOptions = usdFuturesClientOption, SpotApiOptions = spotClientOption }); } public override IList GetIsolatedMarginAccountAssets() { var r = binanceClient.SpotApi.Account.GetIsolatedMarginAccountAsync().Result; if (!r.Success) throw new Exception($"获取逐仓杠杆账户信息失败 {r.Error?.Message}"); return r.Data.Assets.Select(asset => new IsolatedMarginAccountAsset() { Symbol = asset.Symbol, BaseAsset = asset.BaseAsset.Asset, BaseBorrowed = asset.BaseAsset.Borrowed, BaseFree = asset.BaseAsset.Free, BaseInterest = asset.BaseAsset.Interest, BaseLocked = asset.BaseAsset.Locked, BaseNetAsset = asset.BaseAsset.NetAsset, QuoteAsset = asset.QuoteAsset.Asset, QuoteBorrowed = asset.QuoteAsset.Borrowed, QuoteFree = asset.QuoteAsset.Free, QuoteInterest = asset.QuoteAsset.Interest, QuoteLocked = asset.QuoteAsset.Locked, QuoteNetAsset = asset.QuoteAsset.NetAsset }).ToList(); } public override decimal QueryMaxLoanAmount(string symbol) { var r = binanceClient.SpotApi.Account.GetMarginMaxBorrowAmountAsync("USDT", symbol).Result; if (!r.Success) throw new Exception($"查询最大借币额度失败 {r.Error?.Message}"); return r.Data.Quantity; } public override IsolatedMarginLoanResponse IsolatedMarginLoan(string symbol, decimal loanAmount) { var r = binanceClient.SpotApi.Account.MarginBorrowAsync("USDT", loanAmount, true, symbol).Result; if (!r.Success) throw new Exception($"借币失败 {r.Error?.Message}"); var isolatedMarginAccountAssetList = GetIsolatedMarginAccountAssets(); var currentAsset = isolatedMarginAccountAssetList.FirstOrDefault(s => s.Symbol == symbol); if (currentAsset == null) throw new Exception($"借币已完成,但未查询到{symbol}的资产信息 {r.Error?.Message}"); return new IsolatedMarginLoanResponse() { CurrentLoanAmount = loanAmount, AccountLoanAmount = currentAsset.QuoteBorrowed }; } public override decimal IsolatedMarginRepay(string symbol, decimal repayAmount) { var r = binanceClient.SpotApi.Account.MarginRepayAsync("USDT", repayAmount, true, symbol).Result; if (!r.Success) throw new Exception($"还币失败 {r.Error?.Message}"); var txId = r.Data.TransactionId; var r1 = binanceClient.SpotApi.Account.GetMarginRepaysAsync("USDT", txId, isolatedSymbol: symbol).Result; if (!r1.Success) throw new Exception($"还币成功,查询还贷记录失败 {r1.Error?.Message}"); try { return r1.Data.Rows.ToList().Sum(x => x.Interest); } catch { return 0M; } } public override long IsolatedMarginPlaceOrder(string symbol, Enums.TradeDirection tradeDirection, Enums.OrderType orderType, decimal? quantity = null, decimal? quoteAmount = null, decimal? price = null, decimal? stopPrice = null, string newClientOrderId = "") { var binanceOrderSite = (Binance.Net.Enums.OrderSide)(int)tradeDirection; var binanceOrderType = (Binance.Net.Enums.SpotOrderType)(int)orderType; Binance.Net.Enums.TimeInForce? timeInForce = null; if (orderType == Enums.OrderType.LIMIT || orderType == Enums.OrderType.STOP_LOSS_LIMIT) timeInForce = Binance.Net.Enums.TimeInForce.GoodTillCanceled; var r = binanceClient.SpotApi.Trading.PlaceMarginOrderAsync(symbol, binanceOrderSite, binanceOrderType, quantity, quoteAmount, newClientOrderId, price: price, timeInForce: timeInForce, stopPrice: stopPrice, isIsolated: true, orderResponseType: Binance.Net.Enums.OrderResponseType.Acknowledge).Result; if (!r.Success) throw new Exception($"下单失败 {orderType} {tradeDirection} {r.Error?.Message}"); return r.Data.Id; } public override void CancelIsolateMarginOrder(string symbol, long orderId, string clientOrderId) { _ = binanceClient.SpotApi.Trading.CancelMarginOrderAsync(symbol, orderId, isIsolated: true, newClientOrderId: clientOrderId).Result; } } }