Skip to content

Commit

Permalink
Merge pull request #6 from codez0mb1e/develop
Browse files Browse the repository at this point in the history
Migrate to Binance.Net nuget-package
  • Loading branch information
codez0mb1e authored Sep 26, 2021
2 parents 35b92ba + 35b4c0d commit 1cfebf0
Show file tree
Hide file tree
Showing 64 changed files with 179 additions and 2,038 deletions.
13 changes: 6 additions & 7 deletions src/BinanceBot.Market/BaseMarketBot.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BinanceExchange.API.Models.Request;
using BinanceExchange.API.Models.Response;
using Binance.Net.Objects.Spot.SpotData;
using NLog;

namespace BinanceBot.Market
Expand All @@ -17,6 +16,8 @@ public abstract class BaseMarketBot<TStrategy> :
{
protected readonly Logger Logger;

protected readonly TStrategy MarketStrategy;


protected BaseMarketBot(string symbol, TStrategy marketStrategy, Logger logger)
{
Expand All @@ -28,20 +29,18 @@ protected BaseMarketBot(string symbol, TStrategy marketStrategy, Logger logger)

public string Symbol { get; }

public TStrategy MarketStrategy { get; }


public abstract Task RunAsync();

public abstract void Stop();

public abstract Task ValidateConnectionAsync();

public abstract Task<IEnumerable<OrderResponse>> GetOpenedOrdersAsync(string symbol);
public abstract Task<IEnumerable<BinanceOrder>> GetOpenedOrdersAsync(string symbol);

public abstract Task CancelOrdersAsync(IEnumerable<OrderResponse> orders);
public abstract Task CancelOrdersAsync(IEnumerable<BinanceOrder> orders);

public abstract Task<BaseCreateOrderResponse> CreateOrderAsync(CreateOrderRequest order);
public abstract Task<BinancePlacedOrder> CreateOrderAsync(CreateOrderRequest order);


public abstract void Dispose();
Expand Down
5 changes: 3 additions & 2 deletions src/BinanceBot.Market/BinanceBot.Market.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
<LangVersion>9.0</LangVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\BinanceDotNet.BinanceExchange.API\BinanceDotNet.BinanceExchange.API.csproj" />
<PackageReference Include="Binance.Net" Version="7.2.1" />
<PackageReference Include="NLog" Version="4.7.11" />
</ItemGroup>

</Project>
29 changes: 29 additions & 0 deletions src/BinanceBot.Market/CreateOrderRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Binance.Net.Enums;

namespace BinanceBot.Market
{
/// <summary>
/// Request object used to create a new Binance order
/// </summary>
public class CreateOrderRequest
{
public string Symbol { get; set; }

public OrderSide Side { get; set; }

public OrderType Type { get; set; }

public TimeInForce? TimeInForce { get; set; }

public decimal Quantity { get; set; }

public decimal? Price { get; set; }

public string NewClientOrderId { get; set; }

public decimal? StopPrice { get; set; }

public decimal? IcebergQuantity { get; set; }
public int? RecvWindow { get; set; }
}
}
10 changes: 4 additions & 6 deletions src/BinanceBot.Market/IMarketBot.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;

using BinanceExchange.API.Models.Request;
using BinanceExchange.API.Models.Response;
using Binance.Net.Objects.Spot.SpotData;


namespace BinanceBot.Market
Expand Down Expand Up @@ -38,18 +36,18 @@ public interface IMarketBot
/// Get currently opened orders
/// </summary>
/// <param name="symbol"></param>
Task<IEnumerable<OrderResponse>> GetOpenedOrdersAsync(string symbol);
Task<IEnumerable<BinanceOrder>> GetOpenedOrdersAsync(string symbol);

/// <summary>
/// Create new order
/// </summary>
/// <param name="order"></param>
Task<BaseCreateOrderResponse> CreateOrderAsync(CreateOrderRequest order);
Task<BinancePlacedOrder> CreateOrderAsync(CreateOrderRequest order);

/// <summary>
/// Cancel orders
/// </summary>
/// <param name="orders"></param>
Task CancelOrdersAsync(IEnumerable<OrderResponse> orders);
Task CancelOrdersAsync(IEnumerable<BinanceOrder> orders);
}
}
11 changes: 6 additions & 5 deletions src/BinanceBot.Market/MarketDepth.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Binance.Net.Enums;
using Binance.Net.Objects;
using BinanceBot.Market.Utility;
using BinanceExchange.API.Enums;
using BinanceExchange.API.Models.Response;


namespace BinanceBot.Market
{
Expand Down Expand Up @@ -76,7 +77,7 @@ public MarketDepth(string symbol)
/// <summary>
/// Update market depth
/// </summary>
public void UpdateDepth(IEnumerable<TradeResponse> asks, IEnumerable<TradeResponse> bids, long updateTime)
public void UpdateDepth(IEnumerable<BinanceOrderBookEntry> asks, IEnumerable<BinanceOrderBookEntry> bids, long updateTime)
{
if (updateTime <= 0)
throw new ArgumentOutOfRangeException(nameof(updateTime));
Expand All @@ -86,11 +87,11 @@ public void UpdateDepth(IEnumerable<TradeResponse> asks, IEnumerable<TradeRespon
if (asks == null && bids == null) return;


void UpdateOrderBook(IEnumerable<TradeResponse> updates, IDictionary<decimal, decimal> orders)
void UpdateOrderBook(IEnumerable<BinanceOrderBookEntry> updates, IDictionary<decimal, decimal> orders)
{
if (updates != null)
{
foreach (TradeResponse t in updates)
foreach (BinanceOrderBookEntry t in updates)
{
if (t.Quantity != IgnoreVolumeValue)
orders[t.Price] = t.Quantity;
Expand Down
21 changes: 12 additions & 9 deletions src/BinanceBot.Market/MarketDepthManager.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System;
using System.Threading.Tasks;
using BinanceExchange.API.Client;
using BinanceExchange.API.Models.Response;
using BinanceExchange.API.Websockets;
using Binance.Net.Interfaces;
using Binance.Net.Objects.Spot.MarketData;
using CryptoExchange.Net.Objects;


namespace BinanceBot.Market
{
Expand All @@ -25,8 +26,8 @@ namespace BinanceBot.Market
/// </remarks>
public class MarketDepthManager
{
private readonly IBinanceRestClient _restClient;
private readonly IBinanceWebSocketClient _webSocketClient;
private readonly IBinanceClient _restClient;
private readonly IBinanceSocketClient _webSocketClient;


/// <summary>
Expand All @@ -36,7 +37,7 @@ public class MarketDepthManager
/// <param name="webSocketClient">Binance WebSocket client</param>
/// <exception cref="ArgumentNullException"><paramref name="binanceRestClient"/> cannot be <see langword="null"/></exception>
/// <exception cref="ArgumentNullException"><paramref name="webSocketClient"/> cannot be <see langword="null"/></exception>
public MarketDepthManager(IBinanceRestClient binanceRestClient, IBinanceWebSocketClient webSocketClient)
public MarketDepthManager(IBinanceClient binanceRestClient, IBinanceSocketClient webSocketClient)
{
_restClient = binanceRestClient ?? throw new ArgumentNullException(nameof(binanceRestClient));
_webSocketClient = webSocketClient ?? throw new ArgumentNullException(nameof(webSocketClient));
Expand All @@ -55,7 +56,8 @@ public async Task BuildAsync(MarketDepth marketDepth, int limit = 100)
if (limit <= 0)
throw new ArgumentOutOfRangeException(nameof(limit));

OrderBookResponse orderBook = await _restClient.GetOrderBookAsync(marketDepth.Symbol, false, limit);
WebCallResult<BinanceOrderBook> response = await _restClient.Spot.Market.GetOrderBookAsync(marketDepth.Symbol, limit);
BinanceOrderBook orderBook = response.Data;

marketDepth.UpdateDepth(orderBook.Asks, orderBook.Bids, orderBook.LastUpdateId);
}
Expand All @@ -70,9 +72,10 @@ public void StreamUpdates(MarketDepth marketDepth)
if (marketDepth == null)
throw new ArgumentNullException(nameof(marketDepth));

_webSocketClient.ConnectToDepthWebSocket(
_webSocketClient.Spot.SubscribeToOrderBookUpdatesAsync(
marketDepth.Symbol,
marketData => marketDepth.UpdateDepth(marketData.AskDepthDeltas, marketData.BidDepthDeltas, marketData.UpdateId));
1000,
marketData => marketDepth.UpdateDepth(marketData.Data.Asks, marketData.Data.Bids, marketData.Data.LastUpdateId));
}
}
}
69 changes: 41 additions & 28 deletions src/BinanceBot.Market/MarketMakerBot.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
// Create test order flag. See more: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#test-new-order-trade
#define TEST_ORDER_CREATION_MODE
#define TEST_ORDER_CREATION_MODE // Test order flag. See details: https://github.com/binance/binance-spot-api-docs/blob/master/rest-api.md#test-new-order-trade

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using BinanceExchange.API.Client;
using BinanceExchange.API.Enums;
using BinanceExchange.API.Models.Request;
using BinanceExchange.API.Models.Response;
using BinanceExchange.API.Websockets;

using Binance.Net.Enums;
using Binance.Net.Interfaces;
using Binance.Net.Objects.Spot.SpotData;
using CryptoExchange.Net.Objects;
using NLog;


Expand All @@ -21,8 +17,8 @@ namespace BinanceBot.Market
/// </summary>
public class MarketMakerBot : BaseMarketBot<NaiveMarketMakerStrategy>
{
private readonly IBinanceRestClient _binanceRestClient;
private readonly IBinanceWebSocketClient _webSocketClient;
private readonly IBinanceClient _binanceRestClient;
private readonly IBinanceSocketClient _webSocketClient;
private readonly MarketDepth _marketDepth;


Expand All @@ -38,8 +34,8 @@ public class MarketMakerBot : BaseMarketBot<NaiveMarketMakerStrategy>
public MarketMakerBot(
string symbol,
NaiveMarketMakerStrategy marketStrategy,
IBinanceRestClient binanceRestClient,
IBinanceWebSocketClient webSocketClient,
IBinanceClient binanceRestClient,
IBinanceSocketClient webSocketClient,
Logger logger) :
base(symbol, marketStrategy, logger)
{
Expand All @@ -53,43 +49,60 @@ public MarketMakerBot(
public override async Task ValidateConnectionAsync()
{
Logger.Info("Testing connection...");
IResponse testConnectResponse = await _binanceRestClient.TestConnectivityAsync();
if (testConnectResponse != null)

CallResult<long> testConnectResponse = await _binanceRestClient.PingAsync().ConfigureAwait(false);

if (testConnectResponse.Error != null)
Logger.Error(testConnectResponse.Error.Message);
else
{
ServerTimeResponse serverTimeResponse = await _binanceRestClient.GetServerTimeAsync();
Logger.Info($"Connection was established successfully. Approximate ping time: {DateTime.UtcNow.Subtract(serverTimeResponse.ServerTime).TotalMilliseconds:F0} ms");
DateTime serverTimeResponse = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
.AddMilliseconds(testConnectResponse.Data/10.0)
.ToLocalTime();

Logger.Info($"Connection was established successfully. Approximate ping time: {DateTime.UtcNow.Subtract(serverTimeResponse).TotalMilliseconds:F0} ms");
}
}


public override async Task<IEnumerable<OrderResponse>> GetOpenedOrdersAsync(string symbol)
public override async Task<IEnumerable<BinanceOrder>> GetOpenedOrdersAsync(string symbol)
{
if (string.IsNullOrEmpty(symbol))
throw new ArgumentException("Invalid symbol value", nameof(symbol));

return await _binanceRestClient.GetCurrentOpenOrdersAsync(new CurrentOpenOrdersRequest { Symbol = symbol });
var response = await _binanceRestClient.Spot.Order.GetOpenOrdersAsync(symbol).ConfigureAwait(false);
return response.Data;
}


public override async Task CancelOrdersAsync(IEnumerable<OrderResponse> orders)
public override async Task CancelOrdersAsync(IEnumerable<BinanceOrder> orders)
{
if (orders == null)
throw new ArgumentNullException(nameof(orders));

foreach (OrderResponse order in orders)
await _binanceRestClient.CancelOrderAsync(new CancelOrderRequest { OrderId = order.OrderId, OriginalClientOrderId = order.ClientOrderId, Symbol = order.Symbol });
foreach (var order in orders)
await _binanceRestClient.Spot.Order.CancelOrderAsync(orderId: order.OrderId, origClientOrderId: order.ClientOrderId, symbol: order.Symbol).ConfigureAwait(false);
}


public override async Task<BaseCreateOrderResponse> CreateOrderAsync(CreateOrderRequest order)
public override async Task<BinancePlacedOrder> CreateOrderAsync(CreateOrderRequest order)
{

#if TEST_ORDER_CREATION_MODE
EmptyResponse response = await _binanceRestClient.CreateTestOrderAsync(order);
return response != null ? new AcknowledgeCreateOrderResponse() : null;
WebCallResult<BinancePlacedOrder> response = await _binanceRestClient.Spot.Order.PlaceTestOrderAsync(
order.Symbol, order.Side, order.Type, order.Quantity,
newClientOrderId:order.NewClientOrderId,
receiveWindow:order.RecvWindow)
.ConfigureAwait(false);
#else
return await _binanceRestClient.CreateOrderAsync(order);
WebCallResult<BinancePlacedOrder> response = await _binanceRestClient.Spot.Order.PlaceOrderAsync(
order.Symbol, order.Side, order.Type, order.Quantity,
newClientOrderId: order.NewClientOrderId,
receiveWindow: order.RecvWindow)
.ConfigureAwait(false);
#endif

return response.Data;
}


Expand Down Expand Up @@ -122,7 +135,7 @@ private async Task OnMarketBestPairChanged(object sender, MarketBestPairChangedE
var openOrdersResponse = await GetOpenedOrdersAsync(Symbol);

// cancel already opened orders (if necessary)
await CancelOrdersAsync(openOrdersResponse);
if (openOrdersResponse != null) await CancelOrdersAsync(openOrdersResponse);

// find new market position
Quote q = MarketStrategy.Process(e.MarketBestPair);
Expand All @@ -136,7 +149,7 @@ private async Task OnMarketBestPairChanged(object sender, MarketBestPairChangedE
Price = q.Price,
Side = q.Direction,
Type = OrderType.Limit,
TimeInForce = TimeInForce.GTC // 'Good Till Cancelled' marketStrategy
TimeInForce = TimeInForce.GoodTillCancel // 'Good Till Cancelled' marketStrategy
};

await CreateOrderAsync(newOrderRequest);
Expand Down
15 changes: 6 additions & 9 deletions src/BinanceBot.Market/NaiveMarketMakerStrategy.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using BinanceExchange.API.Enums;
using Binance.Net.Enums;
using NLog;


Expand Down Expand Up @@ -41,7 +41,7 @@ public Quote Process(MarketDepthPair marketPair)
_logger.Info($"Best ask / bid: {marketPair.Ask.Price} / {marketPair.Bid.Price}. Update Id: {marketPair.UpdateTime}.");

// get price spreads (in percent)
decimal actualSpread = marketPair.PriceSpread.Value / marketPair.MediumPrice.Value * 100; // spread_relative = spread_absolute/price * 100
decimal actualSpread = marketPair.PriceSpread!.Value / marketPair.MediumPrice!.Value * 100; // spread_relative = spread_absolute/price * 100
decimal expectedSpread = _marketStrategyConfig.TradeWhenSpreadGreaterThan;

_logger.Info($"Spread absolute / relative: {marketPair.PriceSpread} / {actualSpread:F3}%. Update Id: {marketPair.UpdateTime}.");
Expand All @@ -54,13 +54,10 @@ public Quote Process(MarketDepthPair marketPair)
decimal orderPrice = marketPair.Bid.Price + extra; // new_price = best_bid + extra

// compute order volume
decimal volumeSpread = marketPair.VolumeSpread.Value;
decimal orderVolume = volumeSpread > _marketStrategyConfig.MaxOrderVolume
? _marketStrategyConfig.MaxOrderVolume // set max volume
: (volumeSpread < _marketStrategyConfig.MinOrderVolume
? _marketStrategyConfig.MinOrderVolume // set min volume
: volumeSpread);

decimal volumeSpread = marketPair.VolumeSpread!.Value;
decimal orderVolume = volumeSpread > _marketStrategyConfig.MaxOrderVolume ?
_marketStrategyConfig.MaxOrderVolume : // set max volume
(volumeSpread < _marketStrategyConfig.MinOrderVolume ? _marketStrategyConfig.MinOrderVolume : volumeSpread); // set min volume

// return new price-volume pair
quote = new Quote(orderPrice, orderVolume, OrderSide.Buy);
Expand Down
2 changes: 1 addition & 1 deletion src/BinanceBot.Market/Quote.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using BinanceExchange.API.Enums;
using Binance.Net.Enums;

namespace BinanceBot.Market
{
Expand Down
2 changes: 1 addition & 1 deletion src/BinanceBot.Market/Utility/QuoteExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using BinanceExchange.API.Enums;
using Binance.Net.Enums;

namespace BinanceBot.Market.Utility
{
Expand Down
Loading

0 comments on commit 1cfebf0

Please sign in to comment.