1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-11 01:46:12 +00:00

Updated SymbolOrderBook

This commit is contained in:
Jan Korf 2019-07-09 12:00:03 +02:00
parent e89df592f5
commit 0d4707f6a5
10 changed files with 109 additions and 47 deletions

View File

@ -23,7 +23,7 @@ namespace CryptoExchange.Net.UnitTests
// arrange
// act
// assert
Assert.Throws(typeof(ArgumentException), () => new TestBaseClient(new ClientOptions() { ApiCredentials = new ApiCredentials(key, secret) }));
Assert.Throws(typeof(ArgumentException), () => new TestBaseClient(new RestClientOptions() { ApiCredentials = new ApiCredentials(key, secret) }));
}
[TestCase]
@ -31,7 +31,7 @@ namespace CryptoExchange.Net.UnitTests
{
// arrange
var stringBuilder = new StringBuilder();
var client = new TestBaseClient(new ClientOptions()
var client = new TestBaseClient(new RestClientOptions()
{
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) }
});
@ -67,7 +67,7 @@ namespace CryptoExchange.Net.UnitTests
{
// arrange
var stringBuilder = new StringBuilder();
var client = new TestBaseClient(new ClientOptions()
var client = new TestBaseClient(new RestClientOptions()
{
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) },
LogVerbosity = verbosity

View File

@ -105,7 +105,7 @@ namespace CryptoExchange.Net.UnitTests
{
// arrange
// act
var client = new TestRestClient(new ClientOptions()
var client = new TestRestClient(new RestClientOptions()
{
BaseAddress = "http://test.address.com",
RateLimiters = new List<IRateLimiter>{new RateLimiterTotal(1, TimeSpan.FromSeconds(1))},
@ -123,7 +123,7 @@ namespace CryptoExchange.Net.UnitTests
public void SettingRateLimitingBehaviourToFail_Should_FailLimitedRequests()
{
// arrange
var client = new TestRestClient(new ClientOptions()
var client = new TestRestClient(new RestClientOptions()
{
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Fail
@ -146,7 +146,7 @@ namespace CryptoExchange.Net.UnitTests
public void SettingRateLimitingBehaviourToWait_Should_DelayLimitedRequests()
{
// arrange
var client = new TestRestClient(new ClientOptions()
var client = new TestRestClient(new RestClientOptions()
{
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Wait
@ -171,7 +171,7 @@ namespace CryptoExchange.Net.UnitTests
public void SettingApiKeyRateLimiter_Should_DelayRequestsFromSameKey()
{
// arrange
var client = new TestRestClient(new ClientOptions()
var client = new TestRestClient(new RestClientOptions()
{
RateLimiters = new List<IRateLimiter> { new RateLimiterAPIKey(1, TimeSpan.FromSeconds(1)) },
RateLimitingBehaviour = RateLimitingBehaviour.Wait,

View File

@ -7,11 +7,11 @@ namespace CryptoExchange.Net.UnitTests
{
public class TestBaseClient: BaseClient
{
public TestBaseClient(): base(new ClientOptions(), null)
public TestBaseClient(): base(new RestClientOptions(), null)
{
}
public TestBaseClient(ClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
public TestBaseClient(RestClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
{
}

View File

@ -16,12 +16,12 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
{
public class TestRestClient: RestClient
{
public TestRestClient() : base(new ClientOptions(), null)
public TestRestClient() : base(new RestClientOptions(), null)
{
RequestFactory = new Mock<IRequestFactory>().Object;
}
public TestRestClient(ClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
public TestRestClient(RestClientOptions exchangeOptions) : base(exchangeOptions, exchangeOptions.ApiCredentials == null ? null : new TestAuthProvider(exchangeOptions.ApiCredentials))
{
RequestFactory = new Mock<IRequestFactory>().Object;
}
@ -108,7 +108,7 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
public class ParseErrorTestRestClient: TestRestClient
{
public ParseErrorTestRestClient() { }
public ParseErrorTestRestClient(ClientOptions exchangeOptions) : base(exchangeOptions) { }
public ParseErrorTestRestClient(RestClientOptions exchangeOptions) : base(exchangeOptions) { }
protected override Error ParseErrorResponse(JToken error)
{

View File

@ -30,7 +30,7 @@ namespace CryptoExchange.Net
public static int LastId => lastId;
protected BaseClient(ExchangeOptions options, AuthenticationProvider authenticationProvider)
protected BaseClient(ClientOptions options, AuthenticationProvider authenticationProvider)
{
log = new Log();
authProvider = authenticationProvider;
@ -40,16 +40,16 @@ namespace CryptoExchange.Net
/// <summary>
/// Configure the client using the provided options
/// </summary>
/// <param name="exchangeOptions">Options</param>
protected void Configure(ExchangeOptions exchangeOptions)
/// <param name="clientOptionsns">Options</param>
protected void Configure(ClientOptions clientOptions)
{
log.UpdateWriters(exchangeOptions.LogWriters);
log.Level = exchangeOptions.LogVerbosity;
log.UpdateWriters(clientOptions.LogWriters);
log.Level = clientOptions.LogVerbosity;
BaseAddress = exchangeOptions.BaseAddress;
apiProxy = exchangeOptions.Proxy;
BaseAddress = clientOptions.BaseAddress;
apiProxy = clientOptions.Proxy;
if (apiProxy != null)
log.Write(LogVerbosity.Info, $"Setting api proxy to {exchangeOptions.Proxy.Host}:{exchangeOptions.Proxy.Port}");
log.Write(LogVerbosity.Info, $"Setting api proxy to {clientOptions.Proxy.Host}:{clientOptions.Proxy.Port}");
}
/// <summary>

View File

@ -7,7 +7,7 @@
<PropertyGroup>
<PackageId>CryptoExchange.Net</PackageId>
<Authors>JKorf</Authors>
<PackageVersion>2.1.4</PackageVersion>
<PackageVersion>2.1.5</PackageVersion>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE</PackageLicenseUrl>

View File

@ -8,9 +8,51 @@ using CryptoExchange.Net.Logging;
namespace CryptoExchange.Net.Objects
{
/// <summary>
/// Options
/// Base options
/// </summary>
public class ExchangeOptions
public class BaseOptions
{
/// <summary>
/// The log verbosity
/// </summary>
public LogVerbosity LogVerbosity { get; set; } = LogVerbosity.Info;
/// <summary>
/// The log writers
/// </summary>
public List<TextWriter> LogWriters { get; set; } = new List<TextWriter> { new DebugTextWriter() };
}
/// <summary>
/// Base for order book options
/// </summary>
public class OrderBookOptions: BaseOptions
{
/// <summary>
/// The name of the order book implementation
/// </summary>
public string OrderBookName { get; }
/// <summary>
/// Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped.
/// </summary>
public bool SequenceNumbersAreConsecutive { get; }
/// <summary>
/// </summary>
/// <param name="name">The name of the order book implementation</param>
/// <param name="sequencesAreConsecutive">Whether each update should have a consecutive id number. Used to identify and reconnect when numbers are skipped.</param>
public OrderBookOptions(string name, bool sequencesAreConsecutive)
{
OrderBookName = name;
SequenceNumbersAreConsecutive = sequencesAreConsecutive;
}
}
/// <summary>
/// Base client options
/// </summary>
public class ClientOptions: BaseOptions
{
/// <summary>
@ -27,19 +69,12 @@ namespace CryptoExchange.Net.Objects
/// Proxy to use
/// </summary>
public ApiProxy Proxy { get; set; }
/// <summary>
/// The log verbosity
/// </summary>
public LogVerbosity LogVerbosity { get; set; } = LogVerbosity.Info;
/// <summary>
/// The log writers
/// </summary>
public List<TextWriter> LogWriters { get; set; } = new List<TextWriter> { new DebugTextWriter() };
}
public class ClientOptions: ExchangeOptions
/// <summary>
/// Base for rest client options
/// </summary>
public class RestClientOptions: ClientOptions
{
/// <summary>
/// List of rate limiters to use
@ -56,7 +91,7 @@ namespace CryptoExchange.Net.Objects
/// </summary>
public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30);
public T Copy<T>() where T:ClientOptions, new()
public T Copy<T>() where T:RestClientOptions, new()
{
var copy = new T
{
@ -76,7 +111,10 @@ namespace CryptoExchange.Net.Objects
}
}
public class SocketClientOptions: ExchangeOptions
/// <summary>
/// Base for socket client options
/// </summary>
public class SocketClientOptions: ClientOptions
{
/// <summary>
/// Whether or not the socket should automatically reconnect when losing connection

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@ -9,6 +10,9 @@ using CryptoExchange.Net.Sockets;
namespace CryptoExchange.Net.OrderBook
{
/// <summary>
/// Base for order book implementations
/// </summary>
public abstract class SymbolOrderBook: IDisposable
{
protected readonly List<ProcessBufferEntry> processBuffer;
@ -112,21 +116,20 @@ namespace CryptoExchange.Net.OrderBook
}
}
protected SymbolOrderBook(string id, string symbol, bool sequencesAreConsecutive, LogVerbosity logVerbosity, IEnumerable<TextWriter> logWriters)
protected SymbolOrderBook(string symbol, OrderBookOptions options)
{
this.id = id;
id = options.OrderBookName;
processBuffer = new List<ProcessBufferEntry>();
this.sequencesAreConsecutive = sequencesAreConsecutive;
sequencesAreConsecutive = options.SequenceNumbersAreConsecutive;
Symbol = symbol;
Status = OrderBookStatus.Disconnected;
asks = new SortedList<decimal, OrderBookEntry>();
bids = new SortedList<decimal, OrderBookEntry>(new DescComparer<decimal>());
log = new Log { Level = logVerbosity };
if (logWriters == null)
logWriters = new List<TextWriter> { new DebugTextWriter() };
log.UpdateWriters(logWriters.ToList());
log = new Log { Level = options.LogVerbosity };
var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() };
log.UpdateWriters(writers.ToList());
}
/// <summary>
@ -222,7 +225,7 @@ namespace CryptoExchange.Net.OrderBook
CheckProcessBuffer();
bookSet = true;
log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} initial order book set");
log.Write(LogVerbosity.Debug, $"{id} order book {Symbol} data set: {BidCount} bids, {AskCount} asks");
}
}
@ -309,6 +312,24 @@ namespace CryptoExchange.Net.OrderBook
}
public abstract void Dispose();
public override string ToString()
{
return ToString(3);
}
public string ToString(int numberOfEntries)
{
var result = "";
result += $"Asks ({AskCount}): {Environment.NewLine}";
foreach (var entry in Asks.Take(numberOfEntries).Reverse())
result += $" {entry.Price.ToString(CultureInfo.InvariantCulture).PadLeft(8)} | {entry.Quantity.ToString(CultureInfo.InvariantCulture).PadRight(8)}{Environment.NewLine}";
result += $"Bids ({BidCount}): {Environment.NewLine}";
foreach (var entry in Bids.Take(numberOfEntries))
result += $" {entry.Price.ToString(CultureInfo.InvariantCulture).PadLeft(8)} | {entry.Quantity.ToString(CultureInfo.InvariantCulture).PadRight(8)}{Environment.NewLine}";
return result;
}
}
internal class DescComparer<T> : IComparer<T>

View File

@ -35,7 +35,7 @@ namespace CryptoExchange.Net
public IEnumerable<IRateLimiter> RateLimiters { get; private set; }
public int TotalRequestsMade { get; private set; }
protected RestClient(ClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
protected RestClient(RestClientOptions exchangeOptions, AuthenticationProvider authenticationProvider): base(exchangeOptions, authenticationProvider)
{
Configure(exchangeOptions);
}
@ -44,7 +44,7 @@ namespace CryptoExchange.Net
/// Configure the client using the provided options
/// </summary>
/// <param name="exchangeOptions">Options</param>
protected void Configure(ClientOptions exchangeOptions)
protected void Configure(RestClientOptions exchangeOptions)
{
RequestTimeout = exchangeOptions.RequestTimeout;
RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;

View File

@ -189,7 +189,10 @@ The order book will automatically reconnect when the connection is lost and resy
To stop synchronizing an order book use the `Stop` method.
## Release notes
* Version 2.1.4 - 24 june 201
* Version 2.1.5 - 09 jul 2019
* Updated SymbolOrderBook
* Version 2.1.4 - 24 jun 2019
* Added checks for json deserialization issues
* Version 2.1.3 - 16 may 2019