Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Margin trading support, #184

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,4 @@ obj
.vs
obj
bin
/BinanceExchange.Console - Arnon
ArnonSpam marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions BinanceExchange.API/BinanceExchange.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
Expand Down
55 changes: 55 additions & 0 deletions BinanceExchange.API/Client/BinanceClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,61 @@ public async Task<BaseCreateOrderResponse> CreateOrder(CreateOrderRequest reques

}

/// <summary>
/// Creates an Isolated account order based on the provided request
/// </summary>
/// <param name="request">The <see cref="CreateIsolatedOrderRequest"/> that is used to define the order</param>
/// <returns>This method can return <see cref="AcknowledgeCreateOrderResponse"/>, <see cref="FullCreateOrderResponse"/>
/// or <see cref="ResultCreateOrderResponse"/> based on the provided NewOrderResponseType enum in the request.
/// </returns>
public async Task<BaseCreateOrderResponse> CreateIsolatedOrder(CreateIsolatedOrderRequest request)
{
Guard.AgainstNull(request.Symbol);
Guard.AgainstNull(request.Side);
Guard.AgainstNull(request.Type);
Guard.AgainstNull(request.Quantity);

switch (request.NewOrderResponseType)
{
case NewOrderResponseType.Acknowledge:
return await _apiProcessor.ProcessPostRequest<AcknowledgeCreateOrderResponse>(Endpoints.Account.NewOrder(request));
case NewOrderResponseType.Full:
return await _apiProcessor.ProcessPostRequest<FullCreateOrderResponse>(Endpoints.Account.NewOrder(request));
default:
return await _apiProcessor.ProcessPostRequest<ResultCreateOrderResponse>(Endpoints.Account.NewOrder(request));
}

}

/// <summary>
/// Query account max possible borrow (coin symbol specific)
/// </summary>
/// <param name="request">The <see cref="CreateIsolatedOrderRequest"/> that is used to define the order</param>
/// <returns>This method can return <see cref="AcknowledgeCreateOrderResponse"/>, <see cref="FullCreateOrderResponse"/>
/// or <see cref="ResultCreateOrderResponse"/> based on the provided NewOrderResponseType enum in the request.
/// </returns>
public async Task<MaxBorrowResponse> QueryMaxBorrow(MaxBorrowRequest request)
{
Guard.AgainstNull(request.Asset);
Guard.AgainstNull(request.IsolatedSymbol);

return await _apiProcessor.ProcessGetRequest<MaxBorrowResponse>(Endpoints.Account.NewOrder(request));
}

/// <summary>
/// Creates an order based on the provided request
/// </summary>
/// <param name="request">The <see cref="CreateIsolatedOrderRequest"/> that is used to define the order</param>
/// <returns>This method can return <see cref="AcknowledgeCreateOrderResponse"/>, <see cref="FullCreateOrderResponse"/>
/// or <see cref="ResultCreateOrderResponse"/> based on the provided NewOrderResponseType enum in the request.
/// </returns>
public async Task<dynamic> QueryIsolatedMarginAccountInfo(IsolatedMarginAccountInfoRequest request)
{
Guard.AgainstNull(request.Symbols);

return await _apiProcessor.ProcessGetRequest<dynamic>(Endpoints.Account.NewOrder(request));
}

/// <summary>
/// Creates a test order based on the provided request
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions BinanceExchange.API/Endpoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,17 @@ public static class Endpoints
/// Defaults to API binance domain (https)
/// </summary>
internal static string APIBaseUrl = "https://api.binance.com/api";
internal static string BAPIBaseUrl = "https://api.binance.com/bapi";
internal static string SAPIBaseUrl = "https://api.binance.com/sapi";

/// <summary>
/// Defaults to WAPI binance domain (https)
/// </summary>
internal static string WAPIBaseUrl = "https://api.binance.com/wapi";

private static string APIPrefix { get; } = $"{APIBaseUrl}";
private static string BAPIPrefix { get; } = $"{BAPIBaseUrl}";
private static string SAPIPrefix { get; } = $"{SAPIBaseUrl}/v1";
private static string WAPIPrefix { get; } = $"{WAPIBaseUrl}";

public static class UserStream
Expand Down Expand Up @@ -241,6 +245,24 @@ public static BinanceEndpointData SystemStatus()
{
return new BinanceEndpointData(new Uri($"{WAPIPrefix}/{ApiVersion}/systemStatus.html"), EndpointSecurityType.None);
}

public static BinanceEndpointData NewOrder(CreateIsolatedOrderRequest request)
{
var queryString = GenerateQueryStringFromData(request);
return new BinanceEndpointData(new Uri($"{SAPIPrefix}/margin/order?{queryString}"), EndpointSecurityType.Signed);
}

public static BinanceEndpointData NewOrder(MaxBorrowRequest request)
{
var queryString = GenerateQueryStringFromData(request);
return new BinanceEndpointData(new Uri($"{SAPIPrefix}/margin/maxBorrowable?{queryString}"), EndpointSecurityType.Signed);
}

public static BinanceEndpointData NewOrder(IsolatedMarginAccountInfoRequest request)
{
var queryString = GenerateQueryStringFromData(request);
return new BinanceEndpointData(new Uri($"{SAPIPrefix}/margin/isolated/account?{queryString}"), EndpointSecurityType.Signed);
}
}

private static string GenerateQueryStringFromData(IRequest request)
Expand Down
14 changes: 14 additions & 0 deletions BinanceExchange.API/Enums/SideEffectType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Runtime.Serialization;

namespace BinanceExchange.API.Enums
{
public enum SideEffectType
{
[EnumMember(Value = "NO_SIDE_EFFECT")]
NoSideEffect,
[EnumMember(Value = "MARGIN_BUY")]
MarginBuy,
[EnumMember(Value = "AUTO_REPAY")]
AutoRepay,
}
}
81 changes: 81 additions & 0 deletions BinanceExchange.API/Models/Request/CreateIsolatedOrderRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using BinanceExchange.API.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;
using BinanceExchange.API.Models.Request.Interfaces;
using BinanceExchange.API.Converter;

namespace BinanceExchange.API.Models.Request
{
/// <summary>
/// Request object used to create a new Binance Isolated account order
/// </summary>
[DataContract]
public class CreateIsolatedOrderRequest : IRequest
{
[DataMember(Order = 1)]
[JsonProperty("symbol")]
public string Symbol { get; set; }

[DataMember(Order = 2)]
[JsonProperty("isIsolated")]
public string IsIsolated { get; set; }

[DataMember(Order = 3)]
[JsonProperty("side")]
[JsonConverter(typeof(StringEnumConverter))]
public OrderSide Side { get; set; }

[DataMember(Order = 4)]
[JsonProperty("type")]
[JsonConverter(typeof(StringEnumConverter))]
public OrderType Type { get; set; }

[DataMember(Order = 5)]
[JsonProperty("quantity")]
[JsonConverter(typeof(StringDecimalConverter))]
public decimal Quantity { get; set; }

[DataMember(Order = 6)]
[JsonProperty("timeInForce")]
[JsonConverter(typeof(StringEnumConverter))]
public TimeInForce? TimeInForce { get; set; }

[DataMember(Order = 7)]
[JsonProperty("price")]
[JsonConverter(typeof(StringDecimalConverter))]
public decimal? Price { get; set; }

[DataMember(Order = 8)]
[JsonProperty("newClientOrderId")]
public string NewClientOrderId { get; set; }

[DataMember(Order = 9)]
[JsonProperty("stopPrice")]
[JsonConverter(typeof(StringDecimalConverter))]
public decimal? StopPrice { get; set; }

[DataMember(Order = 10)]
[JsonProperty("icebergQty")]
[JsonConverter(typeof(StringDecimalConverter))]
public decimal? IcebergQuantity { get; set; }

[DataMember(Order = 11)]
[JsonProperty("newOrderRespType")]
[JsonConverter(typeof(StringEnumConverter))]
public NewOrderResponseType? NewOrderResponseType { get; set; }

[DataMember(Order = 12)]
[JsonProperty("sideEffectType")]
[JsonConverter(typeof(StringEnumConverter))]
public SideEffectType? SideEffectType { get; set; }

[DataMember(Order = 13)]
[JsonProperty("recvWindow")]
public long? RecvWindow { get; set; }

[DataMember(Order = 14)]
[JsonProperty("timeStamp")]
public long TimeStamp { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using BinanceExchange.API.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;
using BinanceExchange.API.Models.Request.Interfaces;
using BinanceExchange.API.Converter;

namespace BinanceExchange.API.Models.Request
{
/// <summary>
/// Request object used to query Binance Isolated account info
/// </summary>
[DataContract]
public class IsolatedMarginAccountInfoRequest : IRequest
{
[DataMember(Order = 1)]
[JsonProperty("symbols")]
public string Symbols { get; set; }

[DataMember(Order = 2)]
[JsonProperty("recvWindow")]
public long? RecvWindow { get; set; }

[DataMember(Order = 3)]
[JsonProperty("timeStamp")]
public long TimeStamp { get; set; }
}
}
32 changes: 32 additions & 0 deletions BinanceExchange.API/Models/Request/MaxBorrowRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using BinanceExchange.API.Enums;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;
using BinanceExchange.API.Models.Request.Interfaces;
using BinanceExchange.API.Converter;

namespace BinanceExchange.API.Models.Request
{
/// <summary>
/// Request object used to query the accoun't max borrow
/// </summary>
[DataContract]
public class MaxBorrowRequest : IRequest
{
[DataMember(Order = 1)]
[JsonProperty("asset")]
public string Asset { get; set; }

[DataMember(Order = 2)]
[JsonProperty("isolatedSymbol")]
public string IsolatedSymbol { get; set; }

[DataMember(Order = 3)]
[JsonProperty("recvWindow")]
public long? RecvWindow { get; set; }

[DataMember(Order = 4)]
[JsonProperty("timeStamp")]
public long TimeStamp { get; set; }
}
}
18 changes: 18 additions & 0 deletions BinanceExchange.API/Models/Response/MaxBorrowResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Runtime.Serialization;
using BinanceExchange.API.Models.Response.Interfaces;

namespace BinanceExchange.API.Models.Response
{
/// <summary>
/// Balance respomse providing information on assets
/// </summary>
[DataContract]
public class MaxBorrowResponse
{
[DataMember(Order = 1)]
public decimal amount { get; set; }

[DataMember(Order = 2)]
public decimal borrowLimit { get; set; }
}
}
Loading