Skip to content

Commit

Permalink
Merge pull request #43 from alokym86/bitmex.com-side-updates
Browse files Browse the repository at this point in the history
Don't use id and index for orderbook price calculation anymore
  • Loading branch information
ridicoulous committed Jun 5, 2023
2 parents 49b5395 + a518480 commit 5927576
Show file tree
Hide file tree
Showing 5 changed files with 5 additions and 116 deletions.
12 changes: 1 addition & 11 deletions Bitmex.Net.Tests/BitmexClientIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,5 @@ public void ShoulThrowError()
Assert.False(order);
Assert.NotNull(order.Error);
}
[Fact]
public void IndexOfXBTUSDShouldBe88()
{
string pair = "XBTUSD";
int expectedIndex = 88;

var socketClient = new BitmexSocketClient();

Assert.True(socketClient.MainSocketStreams.GetIndexAndTickForInstrument(pair).Index == expectedIndex);
}
}
}
}
7 changes: 2 additions & 5 deletions Bitmex.Net/BitmexSocketClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ public class BitmexSocketClientOptions : ClientOptions
{
private const string SocketEndpoint = "wss://ws.bitmex.com/realtime";
private const string TestNetSocketEndpoint = "wss://ws.testnet.bitmex.com/realtime";
public readonly bool LoadInstruments;
public bool SendPingManually = false;


Expand All @@ -24,7 +23,7 @@ public BitmexSocketClientOptions() : this(false, true)
/// <param name="key"></param>
/// <param name="secret"></param>
/// <param name="isTestnet"></param>
/// <param name="loadInstrumentIndexes">If you will subscribe to orderbook, set it to true, cause instrument index and tick size will be used for price calculation</param>
/// <param name="loadInstrumentIndexes">now is obsolete and not used anymore, left for compatibility</param>
public BitmexSocketClientOptions(string key, string secret, bool isTestnet = false, bool loadInstrumentIndexes = true) : this(isTestnet, loadInstrumentIndexes)
{
key.ValidateNotNull(nameof(key));
Expand All @@ -36,18 +35,16 @@ public BitmexSocketClientOptions(string key, string secret, bool isTestnet = fal
///
/// </summary>
/// <param name="isTestnet"></param>
/// <param name="loadInstrumentIndexes">If you will subscribe to orderbook, set it to true, cause instrument index and tick size will be used for price calculation</param>
/// <param name="loadInstrumentIndexes">now is obsolete and not used anymore, left for compatibility</param>
public BitmexSocketClientOptions(bool isTestnet, bool loadInstrumentIndexes=true, SocketApiClientOptions commonStreamsOptions = null) : base()
{
CommonStreamsOptions = commonStreamsOptions ?? new SocketApiClientOptions(isTestnet ? TestNetSocketEndpoint : SocketEndpoint);
LoadInstruments = loadInstrumentIndexes;
IsTestnet = isTestnet;
}

private BitmexSocketClientOptions(BitmexSocketClientOptions baseOn) : base(baseOn)
{
IsTestnet = baseOn.IsTestnet;
LoadInstruments = baseOn.LoadInstruments;
SendPingManually = baseOn.SendPingManually;
CommonStreamsOptions = baseOn.CommonStreamsOptions;
}
Expand Down
79 changes: 0 additions & 79 deletions Bitmex.Net/BitmexSocketStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,13 @@ public class BitmexSocketStream : SocketApiClient
protected Log log;
protected BitmexSocketClient socketClient;
private readonly bool isTestnet;
private bool shouldUseIndexesAndTicksFromBitmex = false;
private object _locker = new object();

public BitmexSocketStream(Log log, BitmexSocketClient bitmexSocketClient, BitmexSocketClientOptions options) : base(log, options, options.CommonStreamsOptions)
{
isTestnet = options.IsTestnet;
this.log = log;
this.socketClient = bitmexSocketClient;

if (options.LoadInstruments)
{
shouldUseIndexesAndTicksFromBitmex = true;
Task.Run( async () => await GetInstrumentsTickerAndIndices());
}
}

#region events
Expand Down Expand Up @@ -237,14 +230,6 @@ public async Task<CallResult<UpdateSubscription>> SubscribeAsync(BitmexSubscribe
var result = Deserialize<BitmexSocketEvent<BitmexOrderBookEntry>>(token);
if (result.Success)
{
if (shouldUseIndexesAndTicksFromBitmex)
{
foreach (var level in result.Data.Data)
{
var symbolTickInfo = GetIndexAndTickForInstrument(level.Symbol);
level.SetPrice(symbolTickInfo.Index, symbolTickInfo.TickSize);
}
}
OnOrderBookL2_25Update?.Invoke(result.Data);
}
else
Expand All @@ -256,14 +241,6 @@ public async Task<CallResult<UpdateSubscription>> SubscribeAsync(BitmexSubscribe
var result = Deserialize<BitmexSocketEvent<BitmexOrderBookEntry>>(token);
if (result.Success)
{
if (shouldUseIndexesAndTicksFromBitmex)
{
foreach (var level in result.Data.Data)
{
var symbolTickInfo = GetIndexAndTickForInstrument(level.Symbol);
level.SetPrice(symbolTickInfo.Index, symbolTickInfo.TickSize);
}
}
OnorderBookL2Update?.Invoke(result.Data);
}
else
Expand Down Expand Up @@ -475,62 +452,6 @@ private void OnUnsubscribe(BitmexSubscriptionResponse response)
}
}

public BitmexInstrumentIndexWithTick GetIndexAndTickForInstrument(string instrument)
{
if (!shouldUseIndexesAndTicksFromBitmex)
{
return null;
}
if (!areInstrumentsLoaded)
{
GetInstrumentsTickerAndIndices().GetAwaiter().GetResult();
}
return instrumentsIndexesAndTicks[instrument];
}

private async Task GetInstrumentsTickerAndIndices()
{
await instumentGetWaiter.WaitAsync();
if (areInstrumentsLoaded)
{
instumentGetWaiter.Release();
return;
}
using (var bitmexClient = new BitmexClient(new BitmexClientOptions(isTest: isTestnet){LogLevel = this.log?.Level ?? LogLevel.Information}))
{
var getByOnce = 500;
var lastResponseItemCount = 0;
var ind = 0;
do
{
var instruments = await bitmexClient.MarginClient.GetInstrumentsAsync(
new Objects.Requests.BitmexRequestWithFilter()
.WithOldestFirst()
.WithStartingFrom(ind)
.WithResultsCount(500)
.AddColumnsToGetInRequest(new string[] { "symbol", "tickSize" })
);
if (instruments)
{
lastResponseItemCount = instruments.Data.Count;
for (int i = 0; i < instruments.Data.Count; i++)
{
instrumentsIndexesAndTicks.Add(instruments.Data[i].Symbol, new BitmexInstrumentIndexWithTick(ind++, instruments.Data[i].TickSize));
}
}
else
{
log.Write(LogLevel.Error, "Instrument indicies and price ticks for calculation was not obtained");
instumentGetWaiter.Release();
return;
}
}
while (lastResponseItemCount == getByOnce);
}
areInstrumentsLoaded = true;
instumentGetWaiter.Release();
}

#region SocketApiClient abstract methods implementation
#region BaseApiClient abstract methods implementation
protected override AuthenticationProvider CreateAuthenticationProvider(ApiCredentials credentials)
Expand Down
15 changes: 1 addition & 14 deletions Bitmex.Net/BitmexSymbolOrderBook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class BitmexSymbolOrderBook : SymbolOrderBook
private static BitmexSocketOrderBookOptions defaultOrderBookOptions = new BitmexSocketOrderBookOptions("BitmexOrderBook");
private readonly BitmexSocketStream _bitmexSocketStream;
private bool usedNewSocketClient;
private readonly int InstrumentIndex;
private readonly decimal InstrumentTickSize;
private bool IsInititalBookSetted;
private bool isTestnet;
Expand Down Expand Up @@ -62,16 +61,8 @@ public BitmexSymbolOrderBook(string symbol, BitmexSocketOrderBookOptions options
usedNewSocketClient = bitmexSocketClient is null;
var mainClient = bitmexSocketClient ?? new BitmexSocketClient(new BitmexSocketClientOptions(options.IsTestnet){LogLevel = options.LogLevel});
_bitmexSocketStream = (BitmexSocketStream)mainClient.MainSocketStreams;
InstrumentIndex = options.InstrumentIndex ?? _bitmexSocketStream.GetIndexAndTickForInstrument(symbol).Index;
if (symbol == "XBTUSD")
{ //this value is hardcoded
InstrumentTickSize = 0.01m;
}
else
{
InstrumentTickSize = options.TickSize.HasValue ? options.TickSize.Value : _bitmexSocketStream.GetIndexAndTickForInstrument(symbol).TickSize;
}
}

protected override void Dispose(bool disposing)
{
// dispose client only created by this instance not shared socket client
Expand Down Expand Up @@ -145,10 +136,6 @@ private void Update(List<BitmexOrderBookEntry> entries)
{
return;
}
foreach (var e in entries)
{
e.SetPrice(InstrumentIndex, InstrumentTickSize);
}
UpdateOrderBook(LastId, NextId(), entries.Where(e => e.Side == OrderBookEntryType.Bid), entries.Where(e => e.Side == OrderBookEntryType.Ask));
LastAction = DateTime.UtcNow;
}
Expand Down
8 changes: 1 addition & 7 deletions Bitmex.Net/Objects/OrderBookL2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,8 @@ public class BitmexOrderBookEntry : ISymbolOrderBookEntry
public decimal? Size { get; set; }

[JsonProperty("price")]
public decimal? _price { get; set; }

public decimal Price { get => _price ?? 0; set => _price = value; }
public decimal Price { get; set; }

public void SetPrice(int instrumentIndex, decimal tickSize = 0.01m)
{
Price = ((1e8m * instrumentIndex) - Id) * tickSize;
}
}

}
Expand Down

0 comments on commit 5927576

Please sign in to comment.