mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-12 10:26:27 +00:00
Updated SymbolOrderBook
This commit is contained in:
parent
e89df592f5
commit
0d4707f6a5
@ -23,7 +23,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
// arrange
|
// arrange
|
||||||
// act
|
// act
|
||||||
// assert
|
// 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]
|
[TestCase]
|
||||||
@ -31,7 +31,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
var client = new TestBaseClient(new ClientOptions()
|
var client = new TestBaseClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) }
|
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) }
|
||||||
});
|
});
|
||||||
@ -67,7 +67,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var stringBuilder = new StringBuilder();
|
var stringBuilder = new StringBuilder();
|
||||||
var client = new TestBaseClient(new ClientOptions()
|
var client = new TestBaseClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) },
|
LogWriters = new List<TextWriter> { new StringWriter(stringBuilder) },
|
||||||
LogVerbosity = verbosity
|
LogVerbosity = verbosity
|
||||||
|
@ -105,7 +105,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
// act
|
// act
|
||||||
var client = new TestRestClient(new ClientOptions()
|
var client = new TestRestClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
BaseAddress = "http://test.address.com",
|
BaseAddress = "http://test.address.com",
|
||||||
RateLimiters = new List<IRateLimiter>{new RateLimiterTotal(1, TimeSpan.FromSeconds(1))},
|
RateLimiters = new List<IRateLimiter>{new RateLimiterTotal(1, TimeSpan.FromSeconds(1))},
|
||||||
@ -123,7 +123,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public void SettingRateLimitingBehaviourToFail_Should_FailLimitedRequests()
|
public void SettingRateLimitingBehaviourToFail_Should_FailLimitedRequests()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient(new ClientOptions()
|
var client = new TestRestClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
|
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
|
||||||
RateLimitingBehaviour = RateLimitingBehaviour.Fail
|
RateLimitingBehaviour = RateLimitingBehaviour.Fail
|
||||||
@ -146,7 +146,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public void SettingRateLimitingBehaviourToWait_Should_DelayLimitedRequests()
|
public void SettingRateLimitingBehaviourToWait_Should_DelayLimitedRequests()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient(new ClientOptions()
|
var client = new TestRestClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
|
RateLimiters = new List<IRateLimiter> { new RateLimiterTotal(1, TimeSpan.FromSeconds(1)) },
|
||||||
RateLimitingBehaviour = RateLimitingBehaviour.Wait
|
RateLimitingBehaviour = RateLimitingBehaviour.Wait
|
||||||
@ -171,7 +171,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
public void SettingApiKeyRateLimiter_Should_DelayRequestsFromSameKey()
|
public void SettingApiKeyRateLimiter_Should_DelayRequestsFromSameKey()
|
||||||
{
|
{
|
||||||
// arrange
|
// arrange
|
||||||
var client = new TestRestClient(new ClientOptions()
|
var client = new TestRestClient(new RestClientOptions()
|
||||||
{
|
{
|
||||||
RateLimiters = new List<IRateLimiter> { new RateLimiterAPIKey(1, TimeSpan.FromSeconds(1)) },
|
RateLimiters = new List<IRateLimiter> { new RateLimiterAPIKey(1, TimeSpan.FromSeconds(1)) },
|
||||||
RateLimitingBehaviour = RateLimitingBehaviour.Wait,
|
RateLimitingBehaviour = RateLimitingBehaviour.Wait,
|
||||||
|
@ -7,11 +7,11 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
public class TestBaseClient: BaseClient
|
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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,12 +16,12 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|||||||
{
|
{
|
||||||
public class TestRestClient: RestClient
|
public class TestRestClient: RestClient
|
||||||
{
|
{
|
||||||
public TestRestClient() : base(new ClientOptions(), null)
|
public TestRestClient() : base(new RestClientOptions(), null)
|
||||||
{
|
{
|
||||||
RequestFactory = new Mock<IRequestFactory>().Object;
|
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;
|
RequestFactory = new Mock<IRequestFactory>().Object;
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ namespace CryptoExchange.Net.UnitTests.TestImplementations
|
|||||||
public class ParseErrorTestRestClient: TestRestClient
|
public class ParseErrorTestRestClient: TestRestClient
|
||||||
{
|
{
|
||||||
public ParseErrorTestRestClient() { }
|
public ParseErrorTestRestClient() { }
|
||||||
public ParseErrorTestRestClient(ClientOptions exchangeOptions) : base(exchangeOptions) { }
|
public ParseErrorTestRestClient(RestClientOptions exchangeOptions) : base(exchangeOptions) { }
|
||||||
|
|
||||||
protected override Error ParseErrorResponse(JToken error)
|
protected override Error ParseErrorResponse(JToken error)
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
public static int LastId => lastId;
|
public static int LastId => lastId;
|
||||||
|
|
||||||
protected BaseClient(ExchangeOptions options, AuthenticationProvider authenticationProvider)
|
protected BaseClient(ClientOptions options, AuthenticationProvider authenticationProvider)
|
||||||
{
|
{
|
||||||
log = new Log();
|
log = new Log();
|
||||||
authProvider = authenticationProvider;
|
authProvider = authenticationProvider;
|
||||||
@ -40,16 +40,16 @@ namespace CryptoExchange.Net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Configure the client using the provided options
|
/// Configure the client using the provided options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exchangeOptions">Options</param>
|
/// <param name="clientOptionsns">Options</param>
|
||||||
protected void Configure(ExchangeOptions exchangeOptions)
|
protected void Configure(ClientOptions clientOptions)
|
||||||
{
|
{
|
||||||
log.UpdateWriters(exchangeOptions.LogWriters);
|
log.UpdateWriters(clientOptions.LogWriters);
|
||||||
log.Level = exchangeOptions.LogVerbosity;
|
log.Level = clientOptions.LogVerbosity;
|
||||||
|
|
||||||
BaseAddress = exchangeOptions.BaseAddress;
|
BaseAddress = clientOptions.BaseAddress;
|
||||||
apiProxy = exchangeOptions.Proxy;
|
apiProxy = clientOptions.Proxy;
|
||||||
if (apiProxy != null)
|
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>
|
/// <summary>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<PackageVersion>2.1.4</PackageVersion>
|
<PackageVersion>2.1.5</PackageVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/JKorf/CryptoExchange.Net</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/JKorf/CryptoExchange.Net/blob/master/LICENSE</PackageLicenseUrl>
|
||||||
|
@ -8,9 +8,51 @@ using CryptoExchange.Net.Logging;
|
|||||||
namespace CryptoExchange.Net.Objects
|
namespace CryptoExchange.Net.Objects
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options
|
/// Base options
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
@ -27,19 +69,12 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// Proxy to use
|
/// Proxy to use
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ApiProxy Proxy { get; set; }
|
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>
|
/// <summary>
|
||||||
/// List of rate limiters to use
|
/// List of rate limiters to use
|
||||||
@ -56,7 +91,7 @@ namespace CryptoExchange.Net.Objects
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30);
|
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
|
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>
|
/// <summary>
|
||||||
/// Whether or not the socket should automatically reconnect when losing connection
|
/// Whether or not the socket should automatically reconnect when losing connection
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,6 +10,9 @@ using CryptoExchange.Net.Sockets;
|
|||||||
|
|
||||||
namespace CryptoExchange.Net.OrderBook
|
namespace CryptoExchange.Net.OrderBook
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Base for order book implementations
|
||||||
|
/// </summary>
|
||||||
public abstract class SymbolOrderBook: IDisposable
|
public abstract class SymbolOrderBook: IDisposable
|
||||||
{
|
{
|
||||||
protected readonly List<ProcessBufferEntry> processBuffer;
|
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>();
|
processBuffer = new List<ProcessBufferEntry>();
|
||||||
this.sequencesAreConsecutive = sequencesAreConsecutive;
|
sequencesAreConsecutive = options.SequenceNumbersAreConsecutive;
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
Status = OrderBookStatus.Disconnected;
|
Status = OrderBookStatus.Disconnected;
|
||||||
|
|
||||||
asks = new SortedList<decimal, OrderBookEntry>();
|
asks = new SortedList<decimal, OrderBookEntry>();
|
||||||
bids = new SortedList<decimal, OrderBookEntry>(new DescComparer<decimal>());
|
bids = new SortedList<decimal, OrderBookEntry>(new DescComparer<decimal>());
|
||||||
|
|
||||||
log = new Log { Level = logVerbosity };
|
log = new Log { Level = options.LogVerbosity };
|
||||||
if (logWriters == null)
|
var writers = options.LogWriters ?? new List<TextWriter> { new DebugTextWriter() };
|
||||||
logWriters = new List<TextWriter> { new DebugTextWriter() };
|
log.UpdateWriters(writers.ToList());
|
||||||
log.UpdateWriters(logWriters.ToList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -222,7 +225,7 @@ namespace CryptoExchange.Net.OrderBook
|
|||||||
|
|
||||||
CheckProcessBuffer();
|
CheckProcessBuffer();
|
||||||
bookSet = true;
|
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 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>
|
internal class DescComparer<T> : IComparer<T>
|
||||||
|
@ -35,7 +35,7 @@ namespace CryptoExchange.Net
|
|||||||
public IEnumerable<IRateLimiter> RateLimiters { get; private set; }
|
public IEnumerable<IRateLimiter> RateLimiters { get; private set; }
|
||||||
public int TotalRequestsMade { 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);
|
Configure(exchangeOptions);
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ namespace CryptoExchange.Net
|
|||||||
/// Configure the client using the provided options
|
/// Configure the client using the provided options
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exchangeOptions">Options</param>
|
/// <param name="exchangeOptions">Options</param>
|
||||||
protected void Configure(ClientOptions exchangeOptions)
|
protected void Configure(RestClientOptions exchangeOptions)
|
||||||
{
|
{
|
||||||
RequestTimeout = exchangeOptions.RequestTimeout;
|
RequestTimeout = exchangeOptions.RequestTimeout;
|
||||||
RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;
|
RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour;
|
||||||
|
@ -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.
|
To stop synchronizing an order book use the `Stop` method.
|
||||||
|
|
||||||
## Release notes
|
## 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
|
* Added checks for json deserialization issues
|
||||||
|
|
||||||
* Version 2.1.3 - 16 may 2019
|
* Version 2.1.3 - 16 may 2019
|
||||||
|
Loading…
x
Reference in New Issue
Block a user