Skip to content

Commit 21dc1b4

Browse files
committed
Inject MarketSymbol entity
1 parent 18fc676 commit 21dc1b4

8 files changed

Lines changed: 43 additions & 34 deletions

File tree

src/BinanceBot.Market/Abstracts/BaseMarketBot.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Threading.Tasks;
44
using Binance.Net.Objects.Models.Spot;
5+
using BinanceBot.Market.Domain;
56
using NLog;
67

78
namespace BinanceBot.Market;
@@ -19,15 +20,15 @@ public abstract class BaseMarketBot<TStrategy> :
1920
protected readonly TStrategy MarketStrategy;
2021

2122

22-
protected BaseMarketBot(string symbol, TStrategy marketStrategy, Logger logger)
23+
protected BaseMarketBot(MarketSymbol symbol, TStrategy marketStrategy, Logger logger)
2324
{
2425
Symbol = symbol ?? throw new ArgumentNullException(nameof(symbol));
2526
MarketStrategy = marketStrategy ?? throw new ArgumentNullException(nameof(marketStrategy));
2627
Logger = logger ?? LogManager.GetCurrentClassLogger();
2728
}
2829

2930

30-
public string Symbol { get; }
31+
public MarketSymbol Symbol { get; }
3132

3233

3334
public abstract Task RunAsync();

src/BinanceBot.Market/Abstracts/IMarketBot.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections.Generic;
22
using System.Threading.Tasks;
33
using Binance.Net.Objects.Models.Spot;
4+
using BinanceBot.Market.Domain;
45

56

67
namespace BinanceBot.Market;
@@ -13,7 +14,7 @@ public interface IMarketBot
1314
/// <summary>
1415
/// Symbol
1516
/// </summary>
16-
string Symbol { get; }
17+
MarketSymbol Symbol { get; }
1718

1819

1920
/// <summary>

src/BinanceBot.Market/Domain/MarketDepth.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,16 @@ namespace BinanceBot.Market.Domain;
1313
/// </summary>
1414
public class MarketDepth : IMarketDepthPublisher
1515
{
16-
public MarketDepth(string symbol)
16+
public MarketDepth(MarketSymbol symbol)
1717
{
18-
if (string.IsNullOrEmpty(symbol))
18+
if (symbol == null)
1919
throw new ArgumentException("Invalid symbol value", nameof(symbol));
2020

2121
Symbol = symbol;
2222
}
2323

2424

25-
public string Symbol { get; }
26-
25+
public MarketSymbol Symbol { get; }
2726

2827
#region Ask section
2928
private readonly IDictionary<decimal, decimal> _asks = new SortedDictionary<decimal, decimal>();

src/BinanceBot.Market/Domain/Symbol.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public MarketSymbol(string baseAsset, string quoteAsset, ContractType contractTy
3434
/// The Contract type of the symbol
3535
/// </summary>
3636
public ContractType ContractType { get; init; }
37+
38+
override public string ToString() => $"{BaseAsset}/{QuoteAsset} ({ContractType})";
3739
}
3840

3941

src/BinanceBot.Market/MarketMakerBot.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class MarketMakerBot : BaseMarketBot<NaiveMarketMakerStrategy>
3434
/// <exception cref="ArgumentNullException"><paramref name="webSocketClient"/> cannot be <see langword="null"/></exception>
3535
/// <exception cref="ArgumentNullException"><paramref name="binanceRestClient"/> cannot be <see langword="null"/></exception>
3636
public MarketMakerBot(
37-
string symbol,
37+
MarketSymbol symbol,
3838
NaiveMarketMakerStrategy marketStrategy,
3939
IBinanceClient binanceRestClient,
4040
IBinanceSocketClient webSocketClient,
@@ -152,7 +152,7 @@ private async Task OnMarketBestPairChanged(object sender, MarketBestPairChangedE
152152
throw new ArgumentNullException(nameof(e));
153153

154154
// get current opened orders by token
155-
var openOrdersResponse = await GetOpenedOrdersAsync(Symbol);
155+
var openOrdersResponse = await GetOpenedOrdersAsync(Symbol.FullName);
156156

157157
// cancel already opened orders (if necessary)
158158
if (openOrdersResponse != null) await CancelOrdersAsync(openOrdersResponse);
@@ -165,7 +165,7 @@ private async Task OnMarketBestPairChanged(object sender, MarketBestPairChangedE
165165
var newOrderRequest = new CreateOrderRequest
166166
{
167167
// general
168-
Symbol = Symbol,
168+
Symbol = Symbol.FullName,
169169
Side = q.Direction,
170170
OrderType = SpotOrderType.Limit,
171171
// price-quantity

src/BinanceBot.MarketViewer.Console/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ internal static class Program
2121
{
2222
#region Bot Settings
2323
// WARN: Set necessary token here
24-
private const string Symbol = "BNBUSDT";
24+
private static readonly MarketSymbol Symbol = new MarketSymbol("BNB", "USDT", ContractType.Spot);
2525
private const int OrderBookDepth = 10;
2626
private static readonly TimeSpan OrderBookUpdateInterval = TimeSpan.FromMilliseconds(100);
2727
#endregion

tests/BinanceBot.Market.Tests/Core/MarketDepthTests.cs

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,41 @@
1-
using Binance.Net.Enums;
21
using Binance.Net.Objects.Models;
3-
using BinanceBot.Market.Core;
42
using BinanceBot.Market.Domain;
3+
using ContractType = BinanceBot.Market.Domain.ContractType;
54

65
namespace BinanceBot.Market.Tests.Core;
76

87
public class MarketDepthTests
98
{
9+
private static MarketDepth CreateTestMarketDepth() =>
10+
new MarketDepth(new MarketSymbol("BTC", "USDT", ContractType.Spot));
1011
[Fact]
1112
public void Constructor_WithValidSymbol_CreatesInstance()
1213
{
13-
// Arrange & Act
14-
var marketDepth = new MarketDepth("BTCUSDT");
14+
// Arrange
15+
var symbol = new MarketSymbol("BTC", "USDT", ContractType.Spot);
16+
17+
// Act
18+
var marketDepth = new MarketDepth(symbol);
1519

1620
// Assert
17-
Assert.Equal("BTCUSDT", marketDepth.Symbol);
21+
Assert.Equal(symbol, marketDepth.Symbol);
1822
Assert.Null(marketDepth.LastUpdateTime);
1923
Assert.Empty(marketDepth.Asks);
2024
Assert.Empty(marketDepth.Bids);
2125
}
2226

23-
[Theory]
24-
[InlineData("")]
25-
public void Constructor_WithInvalidSymbol_ThrowsArgumentException(string symbol)
27+
[Fact]
28+
public void Constructor_WithNullSymbol_ThrowsArgumentException()
2629
{
2730
// Act & Assert
28-
Assert.Throws<ArgumentException>(() => new MarketDepth(symbol));
31+
Assert.Throws<ArgumentException>(() => new MarketDepth(null));
2932
}
3033

3134
[Fact]
3235
public void UpdateDepth_WithValidData_UpdatesOrderBook()
3336
{
3437
// Arrange
35-
var marketDepth = new MarketDepth("BTCUSDT");
38+
var marketDepth = CreateTestMarketDepth();
3639
var asks = new List<BinanceOrderBookEntry>
3740
{
3841
new() { Price = 50000m, Quantity = 1.5m },
@@ -59,7 +62,7 @@ public void UpdateDepth_WithValidData_UpdatesOrderBook()
5962
public void UpdateDepth_WithOldUpdateTime_IgnoresUpdate()
6063
{
6164
// Arrange
62-
var marketDepth = new MarketDepth("BTCUSDT");
65+
var marketDepth = CreateTestMarketDepth();
6366
var asks = new List<BinanceOrderBookEntry>
6467
{
6568
new() { Price = 50000m, Quantity = 1.5m }
@@ -86,7 +89,7 @@ public void UpdateDepth_WithOldUpdateTime_IgnoresUpdate()
8689
public void UpdateDepth_RemovesPriceLevelWithZeroQuantity()
8790
{
8891
// Arrange
89-
var marketDepth = new MarketDepth("BTCUSDT");
92+
var marketDepth = CreateTestMarketDepth();
9093
var asks = new List<BinanceOrderBookEntry>
9194
{
9295
new() { Price = 50000m, Quantity = 1.5m },
@@ -114,7 +117,7 @@ public void UpdateDepth_RemovesPriceLevelWithZeroQuantity()
114117
public void BestPair_WhenOrderBookIsEmpty_ReturnsNull()
115118
{
116119
// Arrange
117-
var marketDepth = new MarketDepth("BTCUSDT");
120+
var marketDepth = CreateTestMarketDepth();
118121

119122
// Act & Assert
120123
Assert.Null(marketDepth.BestPair);
@@ -124,7 +127,7 @@ public void BestPair_WhenOrderBookIsEmpty_ReturnsNull()
124127
public void BestPair_WhenOrderBookHasData_ReturnsPair()
125128
{
126129
// Arrange
127-
var marketDepth = new MarketDepth("BTCUSDT");
130+
var marketDepth = CreateTestMarketDepth();
128131
var asks = new List<BinanceOrderBookEntry>
129132
{
130133
new() { Price = 50000m, Quantity = 1.5m }
@@ -149,7 +152,7 @@ public void BestPair_WhenOrderBookHasData_ReturnsPair()
149152
public void MarketDepthChanged_RaisesEvent_WhenDepthUpdated()
150153
{
151154
// Arrange
152-
var marketDepth = new MarketDepth("BTCUSDT");
155+
var marketDepth = CreateTestMarketDepth();
153156
MarketDepthChangedEventArgs? eventArgs = null;
154157
marketDepth.MarketDepthChanged += (sender, e) => eventArgs = e;
155158

@@ -175,7 +178,7 @@ public void MarketDepthChanged_RaisesEvent_WhenDepthUpdated()
175178
public void MarketBestPairChanged_RaisesEvent_WhenBestPairChanges()
176179
{
177180
// Arrange
178-
var marketDepth = new MarketDepth("BTCUSDT");
181+
var marketDepth = CreateTestMarketDepth();
179182
var eventRaised = false;
180183
marketDepth.MarketBestPairChanged += (sender, e) => eventRaised = true;
181184

@@ -199,7 +202,7 @@ public void MarketBestPairChanged_RaisesEvent_WhenBestPairChanges()
199202
public void Asks_AreSortedAscending()
200203
{
201204
// Arrange
202-
var marketDepth = new MarketDepth("BTCUSDT");
205+
var marketDepth = CreateTestMarketDepth();
203206
var asks = new List<BinanceOrderBookEntry>
204207
{
205208
new() { Price = 50100m, Quantity = 2.0m },
@@ -223,7 +226,7 @@ public void Asks_AreSortedAscending()
223226
public void Bids_AreSortedDescending()
224227
{
225228
// Arrange
226-
var marketDepth = new MarketDepth("BTCUSDT");
229+
var marketDepth = CreateTestMarketDepth();
227230
var asks = new List<BinanceOrderBookEntry>
228231
{
229232
new() { Price = 50000m, Quantity = 1.0m }
@@ -247,7 +250,7 @@ public void Bids_AreSortedDescending()
247250
public void UpdateDepth_WithZeroOrNegativeUpdateTime_ThrowsArgumentOutOfRangeException()
248251
{
249252
// Arrange
250-
var marketDepth = new MarketDepth("BTCUSDT");
253+
var marketDepth = CreateTestMarketDepth();
251254
var asks = new List<BinanceOrderBookEntry>
252255
{
253256
new() { Price = 50000m, Quantity = 1.5m }

tests/BinanceBot.Market.Tests/MarketDepthManagerTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public MarketDepthManagerTests()
2121
_mockLogger = new Mock<Logger>();
2222
}
2323

24+
private static MarketDepth CreateTestMarketDepth() =>
25+
new MarketDepth(new MarketSymbol("BTC", "USDT", ContractType.Spot));
26+
2427
[Fact]
2528
public void Constructor_WithNullRestClient_ThrowsArgumentNullException()
2629
{
@@ -71,7 +74,7 @@ public async Task BuildAsync_WithZeroOrderBookDepth_ThrowsArgumentOutOfRangeExce
7174
{
7275
// Arrange
7376
var manager = new MarketDepthManager(_mockRestClient.Object, _mockSocketClient.Object, _mockLogger.Object);
74-
var marketDepth = new MarketDepth("BTCUSDT");
77+
var marketDepth = CreateTestMarketDepth();
7578

7679
// Act & Assert
7780
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
@@ -83,7 +86,7 @@ public async Task BuildAsync_WithNegativeOrderBookDepth_ThrowsArgumentOutOfRange
8386
{
8487
// Arrange
8588
var manager = new MarketDepthManager(_mockRestClient.Object, _mockSocketClient.Object, _mockLogger.Object);
86-
var marketDepth = new MarketDepth("BTCUSDT");
89+
var marketDepth = CreateTestMarketDepth();
8790

8891
// Act & Assert
8992
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
@@ -95,7 +98,7 @@ public async Task BuildAsync_WithNegativeUpdateInterval_ThrowsArgumentOutOfRange
9598
{
9699
// Arrange
97100
var manager = new MarketDepthManager(_mockRestClient.Object, _mockSocketClient.Object, _mockLogger.Object);
98-
var marketDepth = new MarketDepth("BTCUSDT");
101+
var marketDepth = CreateTestMarketDepth();
99102

100103
// Act & Assert
101104
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>
@@ -107,7 +110,7 @@ public async Task BuildAsync_WithZeroUpdateInterval_ThrowsArgumentOutOfRangeExce
107110
{
108111
// Arrange
109112
var manager = new MarketDepthManager(_mockRestClient.Object, _mockSocketClient.Object, _mockLogger.Object);
110-
var marketDepth = new MarketDepth("BTCUSDT");
113+
var marketDepth = CreateTestMarketDepth();
111114

112115
// Act & Assert
113116
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(() =>

0 commit comments

Comments
 (0)