diff --git a/src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs b/src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs index 483065d6..6b2beb0b 100644 --- a/src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs +++ b/src/ExchangeSharp/API/Exchanges/BinanceGroup/BinanceGroupCommon.cs @@ -438,20 +438,24 @@ params string[] marketSymbols name.Substring(0, name.IndexOf('@')) ); - // buy=0 -> m = true (The buyer is maker, while the seller is taker). - // buy=1 -> m = false(The seller is maker, while the buyer is taker). - await callback( + ExchangeTrade trade = + token.ParseTradeBinance( + amountKey: "q", + priceKey: "p", + typeKey: "m", + timestampKey: "T", // use trade time (T) instead of event time (E) + timestampType: TimestampType.UnixMilliseconds, + idKey: "a", + typeKeyIsBuyValue: "false"); + trade.Exchange = Name; + trade.Symbol = marketSymbol; + + // buy=0 -> m = true (The buyer is maker, while the seller is taker). + // buy=1 -> m = false(The seller is maker, while the buyer is taker). + await callback( new KeyValuePair( marketSymbol, - token.ParseTradeBinance( - amountKey: "q", - priceKey: "p", - typeKey: "m", - timestampKey: "T", // use trade time (T) instead of event time (E) - timestampType: TimestampType.UnixMilliseconds, - idKey: "a", - typeKeyIsBuyValue: "false" - ) + trade ) ); } @@ -525,7 +529,7 @@ protected override async Task OnGetOrderBookAsync( $"/depth?symbol={marketSymbol}&limit={maxCount}", BaseUrlApi ); - return obj.ParseOrderBookFromJTokenArrays(sequence: "lastUpdateId"); + return obj.ParseOrderBookFromJTokenArrays(exchange: Name, sequence: "lastUpdateId"); } protected override async Task OnGetHistoricalTradesAsync( diff --git a/src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs b/src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs index eaf966ed..f772ed27 100644 --- a/src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/BitBank/ExchangeBitBankAPI.cs @@ -88,6 +88,7 @@ protected override async Task OnGetOrderBookAsync( } result.MarketSymbol = NormalizeMarketSymbol(marketSymbol); } + result.ExchangeName = Name; return result; } diff --git a/src/ExchangeSharp/API/Exchanges/Bitfinex/ExchangeBitfinexAPI.cs b/src/ExchangeSharp/API/Exchanges/Bitfinex/ExchangeBitfinexAPI.cs index 38eb3989..595e9327 100644 --- a/src/ExchangeSharp/API/Exchanges/Bitfinex/ExchangeBitfinexAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/Bitfinex/ExchangeBitfinexAPI.cs @@ -434,6 +434,7 @@ protected override async Task OnGetOrderBookAsync( }; } } + orders.ExchangeName = Name; return orders; } diff --git a/src/ExchangeSharp/API/Exchanges/Gemini/ExchangeGeminiAPI.cs b/src/ExchangeSharp/API/Exchanges/Gemini/ExchangeGeminiAPI.cs index cb220fc0..54e3e68c 100644 --- a/src/ExchangeSharp/API/Exchanges/Gemini/ExchangeGeminiAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/Gemini/ExchangeGeminiAPI.cs @@ -10,17 +10,15 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Text; using System.Threading.Tasks; using System.Web; using System.Xml; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace ExchangeSharp { @@ -35,7 +33,7 @@ private ExchangeGeminiAPI() MarketSymbolIsUppercase = false; MarketSymbolSeparator = string.Empty; WebSocketOrderBookType = WebSocketOrderBookType.FullBookFirstThenDeltas; - RateLimit = new RateGate(1, TimeSpan.FromSeconds(0.5)); + RateLimit = new RateGate(600, TimeSpan.FromSeconds(60)); } private async Task ParseVolumeAsync(JToken token, string symbol) @@ -323,7 +321,7 @@ protected override async Task OnGetOrderBookAsync( JToken obj = await MakeJsonRequestAsync( "/book/" + marketSymbol + "?limit_bids=" + maxCount + "&limit_asks=" + maxCount ); - return obj.ParseOrderBookFromJTokenDictionaries(); + return obj.ParseOrderBookFromJTokenDictionaries(exchange: Name); } protected override async Task OnGetHistoricalTradesAsync( @@ -489,7 +487,7 @@ protected override async Task> OnGetOpenOrderDe { foreach (JToken token in array) { - if (marketSymbol == null || token["symbol"].ToStringInvariant() == marketSymbol) + if (string.IsNullOrEmpty(marketSymbol) || token["symbol"].ToStringInvariant() == marketSymbol) { orders.Add(ParseOrder(token)); } @@ -802,6 +800,8 @@ params string[] marketSymbols foreach (var tradeToken in tradesToken) { var trade = ParseWebSocketTrade(tradeToken); + trade.Exchange = Name; + trade.Symbol = marketSymbol; trade.Flags |= ExchangeTradeFlags.IsFromSnapshot; await callback( new KeyValuePair(marketSymbol, trade) @@ -812,6 +812,7 @@ await callback( { string marketSymbol = token["symbol"].ToStringInvariant(); var trade = ParseWebSocketTrade(token); + trade.Exchange = Name; await callback( new KeyValuePair(marketSymbol, trade) ); diff --git a/src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs b/src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs index 6a2c8576..e59bc5f9 100644 --- a/src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs @@ -770,7 +770,7 @@ protected override async Task OnGetOrderBookAsync( JToken obj = await MakeJsonRequestAsync( "/0/public/Depth?pair=" + marketSymbol + "&count=" + maxCount ); - return obj[marketSymbol].ParseOrderBookFromJTokenArrays(); + return obj[marketSymbol].ParseOrderBookFromJTokenArrays(exchange: Name); } protected override async Task> OnGetRecentTradesAsync( @@ -1154,6 +1154,8 @@ private ExchangePosition ParsePosition(JToken token) { if (kvp.Value["descr"] is JObject descr) { + result.ClientOrderId = kvp.Value["cl_ord_id"].ToObject(); + result.Status = kvp.Value["status"].ToObject(); decimal epochMilliseconds = kvp.Value["opentm"].ToObject(); // Preserve Kraken timestamp decimal precision by converting seconds to milliseconds. epochMilliseconds = epochMilliseconds * 1000; @@ -1399,6 +1401,8 @@ params string[] marketSymbols idKey: null, typeKeyIsBuyValue: "b" ); + trade.Exchange = Name; + trade.Symbol = marketSymbol; await callback( new KeyValuePair(marketSymbol, trade) ); diff --git a/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPI.cs b/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPI.cs index fe07e57b..6d73b1ca 100644 --- a/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPI.cs +++ b/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPI.cs @@ -996,7 +996,7 @@ string marketSymbol // not sure if this is needed, but adding it just in case await new SynchronizationContextRemover(); var lookup = await this.GetExchangeMarketDictionaryFromCacheAsync(); - + if (lookup == null) return null; foreach (var kvp in lookup) { if ( diff --git a/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPIExtensions.cs b/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPIExtensions.cs index 11016076..1abf7aaa 100644 --- a/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPIExtensions.cs +++ b/src/ExchangeSharp/API/Exchanges/_Base/ExchangeAPIExtensions.cs @@ -44,6 +44,7 @@ public static class ExchangeAPIExtensions /// Web socket, call Dispose to close public static async Task GetFullOrderBookWebSocketAsync( this IOrderBookProvider api, + string exchange, Action callback, int maxCount = 100, params string[] symbols @@ -192,6 +193,7 @@ out partialOrderBookQueue fullOrderBook.LastUpdatedUtc = CryptoUtility.UtcNow; trimFullOrderBook(fullOrderBook); + fullOrderBook.ExchangeName = exchange; callback(fullOrderBook); } @@ -469,6 +471,7 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenArray( /// Order book internal static ExchangeOrderBook ParseOrderBookFromJTokenArrays( this JToken token, + string exchange = "unknown", string asks = "asks", string bids = "bids", string sequence = "ts" @@ -518,6 +521,8 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenArrays( Logger.Error($"No bids in {nameof(ParseOrderBookFromJTokenArrays)}"); } + book.ExchangeName = exchange; + return book; } @@ -532,6 +537,7 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenArrays( /// Order book internal static ExchangeOrderBook ParseOrderBookFromJTokenDictionaries( this JToken token, + string exchange = "unknown", string asks = "asks", string bids = "bids", string price = "price", @@ -563,6 +569,8 @@ internal static ExchangeOrderBook ParseOrderBookFromJTokenDictionaries( book.Bids[depth.Price] = depth; } + book.ExchangeName = exchange; + return book; } diff --git a/src/ExchangeSharp/Model/ExchangePosition.cs b/src/ExchangeSharp/Model/ExchangePosition.cs index 42c26f26..08e4e18b 100644 --- a/src/ExchangeSharp/Model/ExchangePosition.cs +++ b/src/ExchangeSharp/Model/ExchangePosition.cs @@ -19,6 +19,16 @@ namespace ExchangeSharp /// public class ExchangePosition { + /// + /// Client Order ID + /// + public string ClientOrderId { get; set; } + + /// + /// Order Status + /// + public string Status { get; set; } + /// /// Market Symbol /// diff --git a/src/ExchangeSharp/Model/ExchangeTrade.cs b/src/ExchangeSharp/Model/ExchangeTrade.cs index 86cc3bab..ad9746ff 100644 --- a/src/ExchangeSharp/Model/ExchangeTrade.cs +++ b/src/ExchangeSharp/Model/ExchangeTrade.cs @@ -24,6 +24,16 @@ namespace ExchangeSharp /// public class ExchangeTrade { + /// + /// Exchange + /// + public string Exchange { get; set; } + + /// + /// Symbol + /// + public string Symbol { get; set; } + /// /// Timestamp ///