币安量化交易
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
6.4 KiB

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<IsolatedMarginAccountAsset> 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;
}
}
}