├── .gitignore ├── Bitfinex ├── packages.config ├── Bitfinex.nuspec ├── Models │ ├── Candles.cs │ ├── Stats.cs │ ├── Books.cs │ ├── Trades.cs │ ├── Common.cs │ └── Tickers.cs ├── Properties │ └── AssemblyInfo.cs ├── JsonConverters │ ├── StatResultConverter.cs │ ├── CandleResultConverter.cs │ ├── BookResultConverter.cs │ ├── TradeResultConverter.cs │ └── TickerResultConverter.cs ├── BitfinexRestClient.cs ├── TickersClient.cs ├── BooksClient.cs ├── Bitfinex.csproj ├── StatsClient.cs ├── TradesClient.cs ├── CandlesClient.cs └── IBitfinexRestClient.cs ├── Bitfinex.Tests ├── packages.config ├── Properties │ └── AssemblyInfo.cs ├── postman.json ├── Models │ ├── TickersTests.cs │ ├── StatsTests.cs │ ├── BooksTests.cs │ ├── CandlesTests.cs │ └── TradesTests.cs └── Bitfinex.Tests.csproj ├── BitfinexAPI.sln ├── README.md └── LICENSE.txt /.gitignore: -------------------------------------------------------------------------------- 1 | /Bitfinex/bin 2 | /Bitfinex/obj 3 | /Bitfinex.Tests/bin 4 | /Bitfinex.Tests/obj 5 | /TestResults 6 | /packages 7 | /.vs 8 | -------------------------------------------------------------------------------- /Bitfinex/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /Bitfinex.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Bitfinex.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("DynamicSites.Bitfinex.Tests")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("DynamicSites.Bitfinex.Tests")] 10 | [assembly: AssemblyCopyright("Copyright © 2017")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("7839f97d-69d4-4125-b543-223b0d307222")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /Bitfinex/Bitfinex.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Bitfinex 5 | $version$ 6 | Jeremy Andrews 7 | Jeremy Andrews 8 | https://github.com/jandrews377/bitfinex-rest/blob/master/LICENSE.txt 9 | https://github.com/jandrews377/bitfinex-rest 10 | false 11 | A C# implementation of the Bitfinex REST API Version 2.0 12 | For full release notes see https://github.com/jandrews377/bitfinex-rest/blob/master/releasenotes.markdown 13 | Copyright 2017 14 | BITFINEX 15 | 16 | -------------------------------------------------------------------------------- /Bitfinex.Tests/postman.json: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Bitfinex", 5 | "_postman_id": "6bfee292-bc0e-38ab-e875-843d23de444f", 6 | "description": "", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "https://api.bitfinex.com/v2/tickers?symbols=tBTCUSD,fUSD", 12 | "request": { 13 | "url": { 14 | "raw": "https://api.bitfinex.com/v2/tickers?symbols=tBTCUSD,fUSD", 15 | "protocol": "https", 16 | "host": [ 17 | "api", 18 | "bitfinex", 19 | "com" 20 | ], 21 | "path": [ 22 | "v2", 23 | "tickers" 24 | ], 25 | "query": [ 26 | { 27 | "key": "symbols", 28 | "value": "tBTCUSD,fUSD", 29 | "equals": true, 30 | "description": "" 31 | } 32 | ], 33 | "variable": [] 34 | }, 35 | "method": "GET", 36 | "header": [], 37 | "body": {}, 38 | "description": "" 39 | }, 40 | "response": [] 41 | } 42 | ] 43 | } -------------------------------------------------------------------------------- /Bitfinex/Models/Candles.cs: -------------------------------------------------------------------------------- 1 | namespace Bitfinex.Models 2 | { 3 | public class Candle 4 | { 5 | /// 6 | /// Millisecond timestamp 7 | /// 8 | public decimal MTS { get; set; } 9 | 10 | /// 11 | /// First execution during the time frame 12 | /// 13 | public double Open { get; set; } 14 | 15 | /// 16 | /// Last execution during the time frame 17 | /// 18 | public double Close { get; set; } 19 | 20 | /// 21 | /// Highest execution during the time frame 22 | /// 23 | public double High { get; set; } 24 | 25 | /// 26 | /// Lowest execution during the timeframe 27 | /// 28 | public double Low { get; set; } 29 | 30 | /// 31 | /// Quantity of symbol traded within the timeframe 32 | /// 33 | public double Volume { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Bitfinex/Models/Stats.cs: -------------------------------------------------------------------------------- 1 | namespace Bitfinex.Models 2 | { 3 | public class Key 4 | { 5 | public string Value { get; set; } 6 | 7 | public static Key TotalOpenPosition => new Key("pos.size"); 8 | 9 | public static Key TotalActiveFunding => new Key("funding.size"); 10 | public static Key ActiveFundingUsedInPositions => new Key("credits.size"); 11 | public static Key ActiveFundingUsedInPositionsPerTradingSymbol => new Key("credits.size.sym"); 12 | 13 | private Key(string value) 14 | { 15 | Value = value; 16 | } 17 | 18 | public override string ToString() 19 | { 20 | return Value; 21 | } 22 | } 23 | 24 | public class Side 25 | { 26 | public string Value { get; set; } 27 | 28 | public static Side Long => new Side("long"); 29 | public static Side Short => new Side("short"); 30 | 31 | private Side(string value) 32 | { 33 | Value = value; 34 | } 35 | 36 | public override string ToString() 37 | { 38 | return Value; 39 | } 40 | } 41 | 42 | public class Stat 43 | { 44 | /// 45 | /// Millisecond timestamp 46 | /// 47 | public decimal MTS { get; set; } 48 | 49 | /// 50 | /// Total amount 51 | /// 52 | public double Value { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Bitfinex/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("DynamicSites.Bitfinex.Framework")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("DynamicSites.Bitfinex.Framework")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("9a3385ac-7e13-4b18-9831-99e487744b97")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /BitfinexAPI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.6 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitfinex.Tests", "Bitfinex.Tests\Bitfinex.Tests.csproj", "{7839F97D-69D4-4125-B543-223B0D307222}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitfinex", "Bitfinex\Bitfinex.csproj", "{9A3385AC-7E13-4B18-9831-99E487744B97}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{35712D31-73E3-46A7-BD18-BD299BBC5A16}" 11 | ProjectSection(SolutionItems) = preProject 12 | Bitfinex.nuspec = Bitfinex.nuspec 13 | LICENSE.txt = LICENSE.txt 14 | README.md = README.md 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {7839F97D-69D4-4125-B543-223B0D307222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {7839F97D-69D4-4125-B543-223B0D307222}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {7839F97D-69D4-4125-B543-223B0D307222}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {7839F97D-69D4-4125-B543-223B0D307222}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {9A3385AC-7E13-4B18-9831-99E487744B97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {9A3385AC-7E13-4B18-9831-99E487744B97}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {9A3385AC-7E13-4B18-9831-99E487744B97}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {9A3385AC-7E13-4B18-9831-99E487744B97}.Release|Any CPU.Build.0 = Release|Any CPU 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bitfinex REST API Version 2.0 Client ![Build status](https://jandrews377.visualstudio.com/_apis/public/build/definitions/bc4a1ea7-aece-4253-8177-8346d98a9c22/1/badge) 2 | 3 | This is a C# implementation of the Bitfinex REST API Version 2.0 (BETA) found here: 4 | 5 | https://bitfinex.readme.io/v2/docs/getting-started 6 | 7 | At this stage it is an ALPHA state. Only the Public Endpoint (https://bitfinex.readme.io/v2/docs/rest-public) has been implemented. In the coming weeks the Authenticated Endpoint (https://bitfinex.readme.io/v2/docs/rest-auth) will be added. 8 | 9 | ### License: Apache License 2.0 10 | 11 | ### Features 12 | 13 | * Easy installation using [NuGet](https://www.nuget.org/packages/Bitfinex) 14 | * Synchronous and Asynchronous methods 15 | 16 | ```csharp 17 | var client = new BitfinexRestClient(); 18 | var tickers = client.GetTickers(new string[] { "tBTCUSD", "tLTCUSD", "fUS" }); 19 | 20 | foreach (var ticker in tickers) 21 | { 22 | var output = new StringBuilder(); 23 | output.AppendLine($"FlashReturnRate: {ticker.FlashReturnRate}"); 24 | output.AppendLine($"BidPeriod: {ticker.BidPeriod}"); 25 | output.AppendLine($"AskPeriod: {ticker.AskPeriod}"); 26 | output.AppendLine($"Symbol: {ticker.Symbol}"); 27 | output.AppendLine($"Bid: {ticker.Bid}"); 28 | output.AppendLine($"BidSize: {ticker.BidSize}"); 29 | output.AppendLine($"Ask: {ticker.Ask}"); 30 | output.AppendLine($"AskSize: {ticker.AskSize}"); 31 | output.AppendLine($"DailyChange: {ticker.DailyChange}"); 32 | output.AppendLine($"DailyChangePercent: {ticker.DailyChangePercent}"); 33 | output.AppendLine($"LastPrice: {ticker.LastPrice}"); 34 | output.AppendLine($"Volume: {ticker.Volume}"); 35 | output.AppendLine($"High: {ticker.High}"); 36 | output.AppendLine($"Low: {ticker.Low}"); 37 | 38 | Console.WriteLine(output); 39 | } 40 | ``` 41 | 42 | Donations gratefully accepted. 43 | Bitcoin: 1NPee1eCWQqmsQwqatdfpgogDrfuwqUZhQ 44 | Ethereum: 0x04f11eefc870ce139954a94cfbf75bdcaf4ede40 45 | -------------------------------------------------------------------------------- /Bitfinex/JsonConverters/StatResultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.Models; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Bitfinex.JsonConverters 8 | { 9 | public class StatsResultConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return objectType == typeof(List); 14 | } 15 | 16 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | var array = JArray.Load(reader); 19 | 20 | var results = new List(); 21 | 22 | foreach (var item in array) 23 | { 24 | var stat = JsonConvert.DeserializeObject(item.ToString(), new StatResultConverter()); 25 | results.Add(stat); 26 | } 27 | 28 | return results; 29 | } 30 | 31 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public override bool CanWrite => false; 37 | } 38 | 39 | public class StatResultConverter : JsonConverter 40 | { 41 | public override bool CanConvert(Type objectType) 42 | { 43 | return objectType == typeof(Stat); 44 | } 45 | 46 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 47 | JsonSerializer serializer) 48 | { 49 | var array = JArray.Load(reader); 50 | 51 | return new Stat 52 | { 53 | MTS = (decimal)array[0], 54 | Value = (double)array[1] 55 | }; 56 | } 57 | 58 | public override bool CanWrite => false; 59 | 60 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 61 | { 62 | throw new NotImplementedException(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Bitfinex/Models/Books.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Bitfinex.Models 4 | { 5 | public enum Precision 6 | { 7 | P0, P1, P2, P3, R0 8 | } 9 | 10 | public interface IBook 11 | { 12 | /// 13 | /// Price level 14 | /// 15 | double Price { get; set; } 16 | 17 | /// 18 | /// Rate level 19 | /// 20 | double Rate { get; set; } 21 | 22 | /// 23 | /// Period level (Funding only) 24 | /// 25 | double Period { get; set; } 26 | 27 | /// 28 | /// Number of orders at that price level 29 | /// 30 | int Count { get; set; } 31 | 32 | /// 33 | /// Total amount available at that price level. 34 | /// 35 | double Amount { get; set; } 36 | } 37 | 38 | public class Book 39 | { 40 | /// 41 | /// Number of orders at that price level 42 | /// 43 | public int Count { get; set; } 44 | 45 | /// 46 | /// Total amount available at that price level. 47 | /// 48 | public double Amount { get; set; } 49 | } 50 | 51 | public class TradingBook : Book, IBook 52 | { 53 | /// 54 | /// Price level 55 | /// 56 | public double Price { get; set; } 57 | 58 | [Obsolete] 59 | public double Rate { get; set; } 60 | 61 | [Obsolete] 62 | public double Period { get; set; } 63 | } 64 | 65 | public class FundingBook : Book, IBook 66 | { 67 | /// 68 | /// Rate at which funding transaction occurred 69 | /// 70 | public double Rate { get; set; } 71 | 72 | /// 73 | /// Amount of time the funding transaction was for 74 | /// 75 | public double Period { get; set; } 76 | 77 | [Obsolete] 78 | public double Price { get; set; } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Bitfinex/Models/Trades.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Bitfinex.Models 4 | { 5 | public interface ITrade 6 | { 7 | decimal ID { get; set; } 8 | 9 | /// 10 | /// Millisecond timestamp 11 | /// 12 | decimal MTS { get; set; } 13 | 14 | /// 15 | /// How much was bought (positive) or sold (negative) 16 | /// 17 | double Amount { get; set; } 18 | 19 | /// 20 | /// Price at which the trade was executed 21 | /// 22 | double Price { get; set; } 23 | 24 | /// 25 | /// Rate at which funding transaction occurred 26 | /// 27 | double Rate { get; set; } 28 | 29 | /// 30 | /// Amount of time the funding transaction was for 31 | /// 32 | TimeSpan Period { get; set; } 33 | } 34 | 35 | public class Trade 36 | { 37 | public decimal ID { get; set; } 38 | 39 | /// 40 | /// Millisecond timestamp 41 | /// 42 | public decimal MTS { get; set; } 43 | 44 | /// 45 | /// How much was bought (positive) or sold (negative) 46 | /// 47 | public double Amount { get; set; } 48 | } 49 | 50 | public class TradingTrade : Trade, ITrade 51 | { 52 | /// 53 | /// Price at which the trade was executed 54 | /// 55 | public double Price { get; set; } 56 | 57 | [Obsolete] 58 | public double Rate { get; set; } 59 | 60 | [Obsolete] 61 | public TimeSpan Period { get; set; } 62 | } 63 | 64 | public class FundingTrade : Trade, ITrade 65 | { 66 | /// 67 | /// Rate at which funding transaction occurred 68 | /// 69 | public double Rate { get; set; } 70 | 71 | /// 72 | /// Amount of time the funding transaction was for 73 | /// 74 | public TimeSpan Period { get; set; } 75 | 76 | [Obsolete] 77 | public double Price { get; set; } 78 | } 79 | } -------------------------------------------------------------------------------- /Bitfinex/JsonConverters/CandleResultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.Models; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Bitfinex.JsonConverters 8 | { 9 | public class CandlesResultConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return objectType == typeof(List); 14 | } 15 | 16 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | var array = JArray.Load(reader); 19 | 20 | var results = new List(); 21 | 22 | foreach (var item in array) 23 | { 24 | var candle = JsonConvert.DeserializeObject(item.ToString(), new CandleResultConverter()); 25 | results.Add(candle); 26 | } 27 | 28 | return results; 29 | } 30 | 31 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public override bool CanWrite => false; 37 | } 38 | 39 | public class CandleResultConverter : JsonConverter 40 | { 41 | public override bool CanConvert(Type objectType) 42 | { 43 | return objectType == typeof(Candle); 44 | } 45 | 46 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 47 | JsonSerializer serializer) 48 | { 49 | var array = JArray.Load(reader); 50 | 51 | return new Candle 52 | { 53 | MTS = (decimal)array[0], 54 | Open = (double)array[1], 55 | Close = (double)array[2], 56 | High = (double)array[3], 57 | Low = (double)array[4], 58 | Volume = (double)array[5] 59 | }; 60 | } 61 | 62 | public override bool CanWrite => false; 63 | 64 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Bitfinex/BitfinexRestClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Bitfinex.Models; 5 | using Newtonsoft.Json; 6 | using RestSharp; 7 | using static System.String; 8 | 9 | namespace Bitfinex 10 | { 11 | public partial class BitfinexRestClient : IBitfinexRestClient 12 | { 13 | private RestClient _client; 14 | 15 | private string _baseUrl = "https://api.bitfinex.com/v2"; 16 | 17 | public string BaseUrl 18 | { 19 | get => _baseUrl; 20 | set 21 | { 22 | _baseUrl = value; 23 | _client = new RestClient(_baseUrl); 24 | } 25 | } 26 | 27 | public CancellationToken CancellationToken { get; set; } 28 | 29 | public BitfinexRestClient() 30 | { 31 | _client = new RestClient(BaseUrl); 32 | CancellationToken = new CancellationTokenSource().Token; 33 | } 34 | 35 | #region private 36 | /// 37 | /// Deserializes JSON to the specified type. 38 | /// 39 | /// 40 | /// 41 | /// 42 | /// 43 | private static object DeserializeObject(string json, JsonConverter converter) 44 | { 45 | try 46 | { 47 | return JsonConvert.DeserializeObject(json, converter); 48 | } 49 | catch (JsonReaderException ex) 50 | { 51 | throw new Exception("Error deserializing response", ex); 52 | } 53 | } 54 | 55 | /// 56 | /// Issue our request. Check our response for an exception as Bitfinex returns Status: OK even when an exception is returned. 57 | /// 58 | /// 59 | /// 60 | /// 61 | private async Task GetResponseAsync(IRestRequest request, CancellationToken token) 62 | { 63 | var response = await _client.ExecuteTaskAsync(request, token); 64 | if (!IsNullOrEmpty(response.ErrorMessage)) throw new Exception(response.ErrorMessage); 65 | 66 | BitfinexException exception = null; 67 | try 68 | { 69 | exception = JsonConvert.DeserializeObject(response.Content, new ExceptionResultConverter()); 70 | } 71 | catch (Exception) 72 | { 73 | // ignored 74 | } 75 | 76 | if (exception != null) throw new Exception($"({exception.ErrorCode}) {exception.Message}"); 77 | 78 | return response; 79 | } 80 | #endregion 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Bitfinex/JsonConverters/BookResultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.Models; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Bitfinex.JsonConverters 8 | { 9 | public class BooksResultConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return objectType == typeof(List); 14 | } 15 | 16 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | var array = JArray.Load(reader); 19 | 20 | var results = new List(); 21 | 22 | foreach (var item in array) 23 | { 24 | var Book = JsonConvert.DeserializeObject(item.ToString(), new BookResultConverter()); 25 | results.Add(Book); 26 | } 27 | 28 | return results; 29 | } 30 | 31 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public override bool CanWrite => false; 37 | } 38 | 39 | public class BookResultConverter : JsonConverter 40 | { 41 | public override bool CanConvert(Type objectType) 42 | { 43 | return objectType == typeof(IBook); 44 | } 45 | 46 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 47 | JsonSerializer serializer) 48 | { 49 | var array = JArray.Load(reader); 50 | 51 | switch (array.Count) 52 | { 53 | case 3: 54 | return JArrayToTradingBook(array); 55 | case 4: 56 | return JArrayToFundingBook(array); 57 | } 58 | 59 | return null; 60 | } 61 | 62 | public override bool CanWrite => false; 63 | 64 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | 69 | private TradingBook JArrayToTradingBook(JArray array) 70 | { 71 | return new TradingBook 72 | { 73 | Price = (double)array[0], 74 | Count = (int)array[1], 75 | Amount = (double)array[2] 76 | }; 77 | } 78 | 79 | private FundingBook JArrayToFundingBook(JArray array) 80 | { 81 | return new FundingBook 82 | { 83 | Rate = (double)array[0], 84 | Period = (int)array[1], 85 | Count = (int)array[2], 86 | Amount = (double)array[3] 87 | }; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Bitfinex/JsonConverters/TradeResultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.Models; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Bitfinex.JsonConverters 8 | { 9 | public class TradesResultConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return objectType == typeof(List); 14 | } 15 | 16 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | var array = JArray.Load(reader); 19 | 20 | var results = new List(); 21 | 22 | foreach (var item in array) 23 | { 24 | var trade = JsonConvert.DeserializeObject(item.ToString(), new TradeResultConverter()); 25 | results.Add(trade); 26 | } 27 | 28 | return results; 29 | } 30 | 31 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public override bool CanWrite => false; 37 | } 38 | 39 | public class TradeResultConverter : JsonConverter 40 | { 41 | public override bool CanConvert(Type objectType) 42 | { 43 | return objectType == typeof(ITrade); 44 | } 45 | 46 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 47 | JsonSerializer serializer) 48 | { 49 | var array = JArray.Load(reader); 50 | 51 | switch (array.Count) 52 | { 53 | case 4: 54 | return JArrayToTradingTrade(array); 55 | case 5: 56 | return JArrayToFundingTrade(array); 57 | } 58 | 59 | return null; 60 | } 61 | 62 | public override bool CanWrite => false; 63 | 64 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 65 | { 66 | throw new NotImplementedException(); 67 | } 68 | 69 | private TradingTrade JArrayToTradingTrade(JArray array) 70 | { 71 | return new TradingTrade 72 | { 73 | ID = (decimal)array[0], 74 | MTS = (decimal)array[1], 75 | Amount = (double)array[2], 76 | Price = (double)array[3] 77 | }; 78 | } 79 | 80 | private FundingTrade JArrayToFundingTrade(JArray array) 81 | { 82 | // TO-DO: Confirm that the value for 'Period' that is returned is actually milliseconds. 83 | 84 | return new FundingTrade 85 | { 86 | ID = (decimal)array[0], 87 | MTS = (decimal)array[1], 88 | Amount = (double)array[2], 89 | Rate = (double)array[3], 90 | Period = new TimeSpan(0,0,0,0,(int)array[4]) 91 | }; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Bitfinex/TickersClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Bitfinex.JsonConverters; 4 | using Bitfinex.Models; 5 | using RestSharp; 6 | using static System.String; 7 | 8 | namespace Bitfinex 9 | { 10 | // All our Ticker methods. 11 | 12 | public partial class BitfinexRestClient 13 | { 14 | /// 15 | /// Get a high-level overview of the specified symbol. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 16 | /// 17 | /// A symbol (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 18 | /// Ticker 19 | public ITicker GetTicker(string symbol) 20 | { 21 | return GetTickerAsync(symbol).Result; 22 | } 23 | 24 | /// 25 | /// Get a high-level overview of the specified symbols. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 26 | /// 27 | /// A list of symbols (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 28 | /// List of tickers 29 | public List GetTickers(string[] symbols) 30 | { 31 | return GetTickersAsync(symbols).Result; 32 | } 33 | 34 | /// 35 | /// Get a high-level overview of the specified symbol. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 36 | /// 37 | /// A symbol (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 38 | /// Ticker 39 | public async Task GetTickerAsync(string symbol) 40 | { 41 | var tickers = await GetTickersAsync(new[] { symbol }); 42 | return tickers[0]; 43 | } 44 | 45 | /// 46 | /// Get a high-level overview of the specified symbols. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 47 | /// 48 | /// A list of symbols (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 49 | /// List of tickers 50 | public async Task> GetTickersAsync(string[] symbols) 51 | { 52 | var symbolsString = Join(",", symbols); 53 | 54 | string url = $"tickers?symbols={symbolsString}"; 55 | var request = new RestRequest(url, Method.GET); 56 | 57 | var response = await GetResponseAsync(request, CancellationToken); 58 | 59 | return (List)DeserializeObject>(response.Content, new TickersResultConverter()); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Bitfinex/BooksClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Bitfinex.JsonConverters; 4 | using Bitfinex.Models; 5 | using RestSharp; 6 | 7 | namespace Bitfinex 8 | { 9 | // All our Books methods. 10 | 11 | public partial class BitfinexRestClient 12 | { 13 | /// 14 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 15 | /// 16 | /// The symbol you want information about. 17 | /// Level of price aggregation (P0, P1, P2, P3, R0) 18 | /// List of books 19 | public List GetBooks(string symbol, Precision precision) 20 | { 21 | return getBooksAsync(symbol, precision, null).Result; 22 | } 23 | 24 | /// 25 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 26 | /// 27 | /// The symbol you want information about. 28 | /// Level of price aggregation (P0, P1, P2, P3, R0) 29 | /// Number of price points 30 | /// List of books 31 | public List GetBooks(string symbol, Precision precision, int len) 32 | { 33 | return getBooksAsync(symbol, precision, len).Result; 34 | } 35 | 36 | /// 37 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 38 | /// 39 | /// The symbol you want information about. 40 | /// Level of price aggregation (P0, P1, P2, P3, R0) 41 | /// List of books 42 | public async Task> GetBooksAsync(string symbol, Precision precision) 43 | { 44 | return await getBooksAsync(symbol, precision, null); 45 | } 46 | 47 | /// 48 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 49 | /// 50 | /// The symbol you want information about. 51 | /// Level of price aggregation (P0, P1, P2, P3, R0) 52 | /// Number of price points 53 | /// List of books 54 | public async Task> GetBooksAsync(string symbol, Precision precision, int len) 55 | { 56 | return await getBooksAsync(symbol, precision, len); 57 | } 58 | 59 | private async Task> getBooksAsync(string symbol, Precision precision, int? len) 60 | { 61 | var url = $"book/{symbol}/{precision}"; 62 | if (len.GetValueOrDefault() != 0) url = url + "?len=" + len; 63 | 64 | var request = new RestRequest(url, Method.GET); 65 | 66 | var response = await GetResponseAsync(request, CancellationToken); 67 | 68 | return (List)DeserializeObject>(response.Content, new BooksResultConverter()); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Bitfinex.Tests/Models/TickersTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Bitfinex.JsonConverters; 3 | using Bitfinex.Models; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using Newtonsoft.Json; 6 | 7 | namespace Bitfinex.Tests.Models 8 | { 9 | [TestClass] 10 | public class TickersTests 11 | { 12 | 13 | [TestMethod] 14 | public void TickerDeserializeTest1() 15 | { 16 | //GET: https://api.bitfinex.com/v2/tickers?symbols=tETHBTC 17 | 18 | string json = "[ \"tETHBTC\", 0.1386, 0.58674268, 0.1391, 89.87488593, -0.00099, -0.0071, 0.13899, 87521.10872248, 0.14331, 0.12951 ]"; 19 | 20 | var ticker = JsonConvert.DeserializeObject(json, new TickerResultConverter()); 21 | 22 | Assert.AreEqual("ETHBTC", ticker.Symbol); 23 | Assert.AreEqual(0.1386, ticker.Bid); 24 | Assert.AreEqual(0.58674268, ticker.BidSize); 25 | Assert.AreEqual(0.1391, ticker.Ask); 26 | Assert.AreEqual(89.87488593, ticker.AskSize); 27 | Assert.AreEqual(-0.00099, ticker.DailyChange); 28 | Assert.AreEqual(-0.0071, ticker.DailyChangePercent); 29 | Assert.AreEqual(0.13899, ticker.LastPrice); 30 | Assert.AreEqual(87521.10872248, ticker.Volume); 31 | Assert.AreEqual(0.14331, ticker.High); 32 | Assert.AreEqual(0.12951, ticker.Low); 33 | 34 | } 35 | 36 | [TestMethod] 37 | public void TickerDeserializeTest2() 38 | { 39 | //GET: https://api.bitfinex.com/v2/tickers?symbols=fUSD 40 | 41 | string json = "[ \"fUSD\", 0.00171431, 0.00156, 30, 998501.81496333, 0.0015, 2, 183396.25235139, -0.0001294, -0.0767, 0.0015586, 55302424.0576984, 0, 0 ]"; 42 | 43 | var ticker = JsonConvert.DeserializeObject(json, new TickerResultConverter()); 44 | 45 | Assert.AreEqual("USD", ticker.Symbol); 46 | Assert.AreEqual(0.00171431, ticker.FlashReturnRate); 47 | Assert.AreEqual(0.00156, ticker.Bid); 48 | Assert.AreEqual(30, ticker.BidPeriod); 49 | Assert.AreEqual(998501.81496333, ticker.BidSize); 50 | Assert.AreEqual(0.0015, ticker.Ask); 51 | Assert.AreEqual(2, ticker.AskPeriod); 52 | Assert.AreEqual(183396.25235139, ticker.AskSize); 53 | Assert.AreEqual(-0.0001294, ticker.DailyChange); 54 | Assert.AreEqual(-0.0767, ticker.DailyChangePercent); 55 | Assert.AreEqual(0.0015586, ticker.LastPrice); 56 | Assert.AreEqual(55302424.0576984, ticker.Volume); 57 | Assert.AreEqual(0, ticker.High); 58 | Assert.AreEqual(0, ticker.Low); 59 | } 60 | 61 | [TestMethod] 62 | public void TickerDeserializeTest3() 63 | { 64 | //GET: https://api.bitfinex.com/v2/tickers?symbols=tBTCUSD,fUSD 65 | 66 | string json = "[ [ \"tBTCUSD\", 2367, 0.5569, 2367.7, 1.34457976, 88.8, 0.039, 2367.7, 52265.08783943, 2397, 2046 ]," + 67 | " [\"fUSD\", 0.00170975, 0.00145, 30, 1527.14753183, 0.00149, 2, 183396.25235139, -0.00015242, -0.0915, 0.00151348, 55001789.95285199, 0, 0 ] ]"; 68 | 69 | var tickers = JsonConvert.DeserializeObject>(json, new TickersResultConverter()); 70 | 71 | Assert.AreEqual(2, tickers.Count); 72 | 73 | } 74 | 75 | [TestMethod] 76 | public void TickerClientTest() 77 | { 78 | var client = new BitfinexRestClient(); 79 | var ticker = client.GetTicker("tBTCUSD"); 80 | 81 | Assert.AreEqual("BTCUSD", ticker.Symbol); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Bitfinex/Bitfinex.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9A3385AC-7E13-4B18-9831-99E487744B97} 8 | Library 9 | Properties 10 | Bitfinex 11 | Bitfinex 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 35 | 36 | 37 | ..\packages\RestSharp.105.2.3\lib\net452\RestSharp.dll 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Bitfinex/JsonConverters/TickerResultConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.Models; 4 | using Newtonsoft.Json; 5 | using Newtonsoft.Json.Linq; 6 | 7 | namespace Bitfinex.JsonConverters 8 | { 9 | public class TickersResultConverter : JsonConverter 10 | { 11 | public override bool CanConvert(Type objectType) 12 | { 13 | return objectType == typeof(List); 14 | } 15 | 16 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 17 | { 18 | var array = JArray.Load(reader); 19 | 20 | var results = new List(); 21 | 22 | foreach (var item in array) 23 | { 24 | var ticker = JsonConvert.DeserializeObject(item.ToString(), new TickerResultConverter()); 25 | results.Add(ticker); 26 | } 27 | 28 | return results; 29 | } 30 | 31 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | 36 | public override bool CanWrite => false; 37 | } 38 | 39 | public class TickerResultConverter : JsonConverter 40 | { 41 | public override bool CanConvert(Type objectType) 42 | { 43 | return objectType == typeof(ITicker); 44 | } 45 | 46 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, 47 | JsonSerializer serializer) 48 | { 49 | var array = JArray.Load(reader); 50 | 51 | var symbol = (string) array[0]; 52 | 53 | if (symbol.StartsWith("t")) return JArrayToTradingTicker(array); 54 | if (symbol.StartsWith("f")) return JArrayToFundingTicker(array); 55 | 56 | return null; 57 | } 58 | 59 | public override bool CanWrite => false; 60 | 61 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 62 | { 63 | throw new NotImplementedException(); 64 | } 65 | 66 | private TradingTicker JArrayToTradingTicker(JArray array) 67 | { 68 | string symbol = (string)array[0]; 69 | string symbolStripped = symbol.Substring(1); 70 | 71 | return new TradingTicker 72 | { 73 | Symbol = symbolStripped, 74 | Bid = (double)array[1], 75 | BidSize = (double)array[2], 76 | Ask = (double)array[3], 77 | AskSize = (double)array[4], 78 | DailyChange = (double)array[5], 79 | DailyChangePercent = (double)array[6], 80 | LastPrice = (double)array[7], 81 | Volume = (double)array[8], 82 | High = (double)array[9], 83 | Low = (double)array[10] 84 | }; 85 | } 86 | 87 | private FundingTicker JArrayToFundingTicker(JArray array) 88 | { 89 | string symbol = (string)array[0]; 90 | string symbolStripped = symbol.Substring(1); 91 | 92 | return new FundingTicker 93 | { 94 | Symbol = symbolStripped, 95 | FlashReturnRate = (double)array[1], 96 | Bid = (double)array[2], 97 | BidPeriod = (int)array[3], 98 | BidSize = (double)array[4], 99 | Ask = (double)array[5], 100 | AskPeriod = (int)array[6], 101 | AskSize = (double)array[7], 102 | DailyChange = (double)array[8], 103 | DailyChangePercent = (double)array[9], 104 | LastPrice = (double)array[10], 105 | Volume = (double)array[11], 106 | High = (double)array[12], 107 | Low = (double)array[13] 108 | }; 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Bitfinex/Models/Common.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Linq; 4 | 5 | namespace Bitfinex.Models 6 | { 7 | public enum Symbol 8 | { 9 | BTCUSD, 10 | LTCUSD, 11 | LTCBTC, 12 | ETHUSD, 13 | ETHBTC, 14 | ETCBTC, 15 | ETCUSD, 16 | RRTUSD, 17 | RRTBTC, 18 | ZECUSD, 19 | ZECBTC, 20 | XMRUSD, 21 | XMRBTC, 22 | DSHUSD, 23 | DSHBTC, 24 | BCCBTC, 25 | BCUBTC, 26 | BCCUSD, 27 | BCUUSD, 28 | XRPUSD, 29 | XRPBTC, 30 | IOTUSD, 31 | IOTBTC, 32 | IOTETH, 33 | EOSUSD, 34 | EOSBTC, 35 | EOSETH, 36 | SANUSD, 37 | SANBTC, 38 | SANETH, 39 | OMGUSD, 40 | OMGBTC, 41 | OMGETH, 42 | BCHUSD, 43 | BCHBTC, 44 | BCHETH 45 | } 46 | 47 | public class TradeSymbol 48 | { 49 | private const string Prefix = "t"; 50 | 51 | private Symbol _symbol { get; } 52 | 53 | public string Value => Prefix + _symbol; 54 | 55 | public static explicit operator TradeSymbol(Symbol symbol) 56 | { 57 | return new TradeSymbol(symbol); 58 | } 59 | 60 | public TradeSymbol(Symbol symbol) 61 | { 62 | _symbol = symbol; 63 | } 64 | 65 | public override string ToString() 66 | { 67 | return Prefix + _symbol; 68 | } 69 | } 70 | 71 | 72 | public enum SortDirection 73 | { 74 | OldestToNewest = 1, NewestToOldest = -1 75 | } 76 | 77 | public class TimeFrame 78 | { 79 | public string Value { get; set; } 80 | 81 | public static TimeFrame Minute => new TimeFrame("1m"); 82 | public static TimeFrame Minute5 => new TimeFrame("5m"); 83 | public static TimeFrame Minute15 => new TimeFrame("15m"); 84 | public static TimeFrame Minute30 => new TimeFrame("30m"); 85 | public static TimeFrame Hour => new TimeFrame("1h"); 86 | public static TimeFrame Hour3 => new TimeFrame("3h"); 87 | public static TimeFrame Hour6 => new TimeFrame("6h"); 88 | public static TimeFrame Hour12 => new TimeFrame("12h"); 89 | public static TimeFrame Day => new TimeFrame("1D"); 90 | public static TimeFrame Week => new TimeFrame("7D"); 91 | public static TimeFrame Fortnight => new TimeFrame("14D"); 92 | public static TimeFrame Month => new TimeFrame("1M"); 93 | 94 | private TimeFrame(string value) 95 | { 96 | Value = value; 97 | } 98 | 99 | public override string ToString() 100 | { 101 | return Value; 102 | } 103 | } 104 | 105 | public class Section 106 | { 107 | public string Value { get; set; } 108 | 109 | public static Section Last => new Section("last"); 110 | public static Section Historical => new Section("hist"); 111 | 112 | private Section(string value) 113 | { 114 | Value = value; 115 | } 116 | 117 | public override string ToString() 118 | { 119 | return Value; 120 | } 121 | } 122 | 123 | public class BitfinexException : Exception 124 | { 125 | public int ErrorCode { get; set; } 126 | public string Message { get; set; } 127 | } 128 | 129 | public class ExceptionResultConverter : JsonConverter 130 | { 131 | public override bool CanConvert(Type objectType) 132 | { 133 | return objectType == typeof(BitfinexException); 134 | } 135 | 136 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 137 | { 138 | var array = JArray.Load(reader); 139 | 140 | if ((string)array[0] == "error") 141 | { 142 | 143 | return new BitfinexException 144 | { 145 | ErrorCode = (int)array[1], 146 | Message = (string)array[2] 147 | }; 148 | } 149 | 150 | return null; 151 | } 152 | 153 | public override bool CanWrite => false; 154 | 155 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 156 | { 157 | throw new NotImplementedException(); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Bitfinex/StatsClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Bitfinex.JsonConverters; 5 | using Bitfinex.Models; 6 | using RestSharp; 7 | 8 | namespace Bitfinex 9 | { 10 | // All our Stats methods. 11 | 12 | public partial class BitfinexRestClient 13 | { 14 | /// 15 | /// Get statistics about the requested pair. 16 | /// 17 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 18 | /// The symbol you want information about. 19 | /// Available values: "long", "short" 20 | /// Available values: "last", "hist" 21 | /// List of MTS and Value stats for the requested pair 22 | public List GetStats(Key key, Symbol symbol, Side side, Section section) 23 | { 24 | return getStatsAsync(key, symbol, side, section).Result; 25 | } 26 | 27 | /// 28 | /// Get statistics about the requested pair. 29 | /// 30 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 31 | /// The symbol you want information about. 32 | /// Available values: "long", "short" 33 | /// Available values: "last", "hist" 34 | /// Default new > old 35 | /// List of MTS and Value stats for the requested pair 36 | public List GetStats(Key key, Symbol symbol, Side side, Section section, SortDirection sortDirection) 37 | { 38 | return getStatsAsync(key, symbol, side, section, sortDirection).Result; 39 | } 40 | 41 | /// 42 | /// Get statistics about the requested pair. 43 | /// 44 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 45 | /// The symbol you want information about. 46 | /// Available values: "long", "short" 47 | /// Available values: "last", "hist" 48 | /// List of MTS and Value stats for the requested pair 49 | public async Task> GetStatsAsync(Key key, Symbol symbol, Side side, Section section) 50 | { 51 | return await getStatsAsync(key, symbol, side, section); 52 | } 53 | 54 | /// 55 | /// Get statistics about the requested pair. 56 | /// 57 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 58 | /// The symbol you want information about. 59 | /// Available values: "long", "short" 60 | /// Available values: "last", "hist" 61 | /// Default new > old 62 | /// List of MTS and Value stats for the requested pair 63 | public async Task> GetStatsAsync(Key key, Symbol symbol, Side side, Section section, SortDirection sortDirection) 64 | { 65 | return await getStatsAsync(key, symbol, side, section, sortDirection); 66 | } 67 | 68 | private async Task> getStatsAsync(Key key, Symbol symbol, Side side, Section section, SortDirection? sortDirection = null) 69 | { 70 | var size = TimeFrame.Minute; 71 | 72 | var url = $"stats1/{key}:{size}:{(TradeSymbol)symbol}:{side}/{section}"; 73 | if (sortDirection != null) url = url + "?sort=" + (int)sortDirection; 74 | 75 | var request = new RestRequest(url, Method.GET); 76 | 77 | var response = await GetResponseAsync(request, CancellationToken); 78 | 79 | // We could have recieved a single stat. 80 | try 81 | { 82 | var stat = (Stat)DeserializeObject(response.Content, new StatResultConverter()); 83 | if (stat != null) return new List() { stat }; 84 | } 85 | catch (Exception) 86 | { 87 | // ignored 88 | } 89 | 90 | return (List)DeserializeObject>(response.Content, new StatsResultConverter()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Bitfinex/Models/Tickers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Bitfinex.Models 4 | { 5 | public interface ITicker 6 | { 7 | /// 8 | /// Flash Return Rate - average of all fixed rate funding over the last hour 9 | /// 10 | double FlashReturnRate { get; set; } 11 | 12 | /// 13 | /// Bid period covered in days 14 | /// 15 | int BidPeriod { get; set; } 16 | 17 | /// 18 | /// Ask period covered in days 19 | /// 20 | int AskPeriod { get; set; } 21 | 22 | string Symbol { get; set; } 23 | 24 | /// 25 | /// Price of last highest bid 26 | /// 27 | double Bid { get; set; } 28 | 29 | /// 30 | /// Size of the last highest bid 31 | /// 32 | double BidSize { get; set; } 33 | 34 | /// 35 | /// Price of last lowest ask 36 | /// 37 | double Ask { get; set; } 38 | 39 | /// 40 | /// Size of the last lowest ask 41 | /// 42 | double AskSize { get; set; } 43 | 44 | /// 45 | /// Amount that the last price has changed since yesterday 46 | /// 47 | double DailyChange { get; set; } 48 | 49 | /// 50 | /// Amount that the price has changed expressed in percentage terms 51 | /// 52 | double DailyChangePercent { get; set; } 53 | 54 | /// 55 | /// Price of the last trade 56 | /// 57 | double LastPrice { get; set; } 58 | 59 | /// 60 | /// Daily volume 61 | /// 62 | double Volume { get; set; } 63 | 64 | 65 | /// 66 | /// Daily high 67 | /// 68 | double High { get; set; } 69 | 70 | /// 71 | /// Daily low 72 | /// 73 | double Low { get; set; } 74 | } 75 | 76 | public class TradingTicker : Ticker, ITicker 77 | { 78 | [Obsolete] 79 | public double FlashReturnRate { get; set; } 80 | 81 | [Obsolete] 82 | public int BidPeriod { get; set; } 83 | 84 | [Obsolete] 85 | public int AskPeriod { get; set; } 86 | } 87 | 88 | public class FundingTicker : Ticker, ITicker 89 | { 90 | /// 91 | /// Flash Return Rate - average of all fixed rate funding over the last hour 92 | /// 93 | public double FlashReturnRate { get; set; } 94 | 95 | /// 96 | /// Bid period covered in days 97 | /// 98 | public int BidPeriod { get; set; } 99 | 100 | /// 101 | /// Ask period covered in days 102 | /// 103 | public int AskPeriod { get; set; } 104 | } 105 | 106 | public class Ticker 107 | { 108 | public string Symbol { get; set; } 109 | 110 | /// 111 | /// Price of last highest bid 112 | /// 113 | public double Bid { get; set; } 114 | 115 | /// 116 | /// Size of the last highest bid 117 | /// 118 | public double BidSize { get; set; } 119 | 120 | /// 121 | /// Price of last lowest ask 122 | /// 123 | public double Ask { get; set; } 124 | 125 | /// 126 | /// Size of the last lowest ask 127 | /// 128 | public double AskSize { get; set; } 129 | 130 | /// 131 | /// Amount that the last price has changed since yesterday 132 | /// 133 | public double DailyChange { get; set; } 134 | 135 | /// 136 | /// Amount that the price has changed expressed in percentage terms 137 | /// 138 | public double DailyChangePercent { get; set; } 139 | 140 | /// 141 | /// Price of the last trade 142 | /// 143 | public double LastPrice { get; set; } 144 | 145 | /// 146 | /// Daily volume 147 | /// 148 | public double Volume { get; set; } 149 | 150 | /// 151 | /// Daily high 152 | /// 153 | public double High { get; set; } 154 | 155 | /// 156 | /// Daily low 157 | /// 158 | public double Low { get; set; } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Bitfinex.Tests/Bitfinex.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {7839F97D-69D4-4125-B543-223B0D307222} 8 | Library 9 | Properties 10 | Bitfinex.Tests 11 | Bitfinex.Tests 12 | v4.5.2 13 | 512 14 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 15 | 15.0 16 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 17 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 18 | False 19 | UnitTest 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\Debug\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\Release\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | ..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll 43 | 44 | 45 | ..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll 46 | 47 | 48 | ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {9a3385ac-7e13-4b18-9831-99e487744b97} 64 | Bitfinex 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /Bitfinex.Tests/Models/StatsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Bitfinex.JsonConverters; 3 | using Bitfinex.Models; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using Newtonsoft.Json; 6 | 7 | namespace Bitfinex.Tests.Models 8 | { 9 | [TestClass] 10 | public class StatsTests 11 | { 12 | [TestMethod] 13 | public void StatsDeserializeTest1() 14 | { 15 | //GET: https://api.bitfinex.com/v2/stats1/pos.size:1m:tBTCUSD:long/hist 16 | string json = "[ [ 1500093840000, 15231.85983157 ], [ 1500093780000, 15222.20717334 ], [ 1500093720000, 15232.36907505 ], [ 1500093660000, 15228.48695498 ], [ 1500093600000, 15229.10184868 ], [ 1500093540000, 15222.826221 ], [ 1500093480000, 15219.26732882 ], [ 1500093420000, 15224.30928207 ], [ 1500093360000, 15230.89866354 ], [ 1500093300000, 15220.86558719 ], [ 1500093240000, 15226.95297291 ], [ 1500093180000, 15225.29479749 ], [ 1500093120000, 15241.31420914 ], [ 1500093060000, 15293.55050882 ], [ 1500093000000, 15293.60275019 ], [ 1500092940000, 15290.91730215 ], [ 1500092880000, 15289.19255742 ], [ 1500092820000, 15295.95908076 ], [ 1500092760000, 15296.97433591 ], [ 1500092700000, 15311.40258141 ], [ 1500092640000, 15313.66587808 ], [ 1500092580000, 15318.39892697 ], [ 1500092520000, 15320.59299776 ], [ 1500092460000, 15325.2897859 ], [ 1500092400000, 15398.21133439 ], [ 1500092340000, 15400.24352068 ], [ 1500092280000, 15403.7085432 ], [ 1500092220000, 15411.30088097 ], [ 1500092160000, 15416.12045021 ], [ 1500092100000, 15413.86114722 ], [ 1500092040000, 15399.15144811 ], [ 1500091980000, 15422.14545073 ], [ 1500091920000, 15424.60621835 ], [ 1500091860000, 15425.89809248 ], [ 1500091800000, 15416.92356844 ], [ 1500091740000, 15394.64693962 ], [ 1500091680000, 15408.01395342 ], [ 1500091620000, 15408.42273459 ], [ 1500091560000, 15431.66084099 ], [ 1500091500000, 15440.32333756 ], [ 1500091440000, 15438.89097298 ], [ 1500091380000, 15428.85219372 ], [ 1500091320000, 15429.10151933 ], [ 1500091260000, 15439.93907027 ], [ 1500091200000, 15432.4930594 ], [ 1500091140000, 15405.65069239 ], [ 1500091080000, 15373.78321039 ], [ 1500091020000, 15318.22377754 ], [ 1500090960000, 15269.37540778 ], [ 1500090900000, 15299.09734332 ], [ 1500090840000, 15333.89672277 ], [ 1500090780000, 15357.80946038 ], [ 1500090720000, 15353.04964833 ], [ 1500090660000, 15353.28792585 ], [ 1500090600000, 15352.22412785 ], [ 1500090540000, 15352.06143252 ], [ 1500090480000, 15336.62951844 ], [ 1500090420000, 15333.25901925 ], [ 1500090360000, 15320.13558957 ], [ 1500090300000, 15320.73408149 ], [ 1500090240000, 15311.54725422 ], [ 1500090180000, 15306.25371221 ], [ 1500090120000, 15306.3637642 ], [ 1500090060000, 15270.90919689 ], [ 1500090000000, 15233.06690044 ], [ 1500089940000, 15218.81492598 ], [ 1500089880000, 15217.33416351 ], [ 1500089820000, 15214.19321812 ], [ 1500089760000, 15211.33440694 ], [ 1500089700000, 15275.17695305 ], [ 1500089640000, 15269.80908519 ], [ 1500089580000, 15316.08834545 ], [ 1500089520000, 15329.31148792 ], [ 1500089460000, 15338.80853724 ], [ 1500089400000, 15350.79856656 ], [ 1500089340000, 15357.38565195 ], [ 1500089280000, 15480.48521171 ], [ 1500089220000, 15479.23740771 ], [ 1500089160000, 15479.03740771 ], [ 1500089100000, 15480.36830215 ], [ 1500089040000, 15480.15977308 ], [ 1500088980000, 15471.1140165 ], [ 1500088920000, 15470.28860656 ], [ 1500088860000, 15467.86359383 ], [ 1500088800000, 15473.44259383 ], [ 1500088740000, 15473.44259383 ], [ 1500088680000, 15473.37657767 ], [ 1500088620000, 15464.62341721 ], [ 1500088560000, 15439.77642582 ], [ 1500088500000, 15436.91659359 ], [ 1500088440000, 15435.21215708 ], [ 1500088380000, 15439.85816968 ], [ 1500088320000, 15440.00508375 ], [ 1500088260000, 15440.01328803 ], [ 1500088200000, 15477.66892043 ], [ 1500088140000, 15473.41498496 ], [ 1500088080000, 15471.93962585 ], [ 1500088020000, 15476.27890248 ], [ 1500087960000, 15468.04539202 ], [ 1500087900000, 15467.27761746 ], [ 1500087840000, 15476.67295242 ], [ 1500087780000, 15464.59910546 ], [ 1500087720000, 15468.88825221 ], [ 1500087660000, 15463.95204925 ], [ 1500087600000, 15481.00653205 ], [ 1500087540000, 15482.93320915 ], [ 1500087480000, 15481.39998574 ], [ 1500087420000, 15481.01823029 ], [ 1500087360000, 15459.57938083 ], [ 1500087300000, 15448.05521381 ], [ 1500087240000, 15435.04350378 ], [ 1500087180000, 15427.45971061 ], [ 1500087120000, 15494.45581034 ], [ 1500087060000, 15506.46048953 ], [ 1500087000000, 15510.59625666 ], [ 1500086940000, 15527.59412255 ], [ 1500086880000, 15529.46401016 ], [ 1500086820000, 15524.67755702 ], [ 1500086760000, 15517.59401016 ], [ 1500086700000, 15519.3946787 ] ]"; 17 | 18 | var stats = JsonConvert.DeserializeObject>(json, new StatsResultConverter()); 19 | 20 | Assert.AreEqual(120, stats.Count); 21 | 22 | var stat = stats[0]; 23 | 24 | Assert.AreEqual(1500093840000, stat.MTS); 25 | Assert.AreEqual(15231.85983157, stat.Value); 26 | } 27 | 28 | [TestMethod] 29 | public void StatsDeserializeTest2() 30 | { 31 | //GET: https://api.bitfinex.com/v2/stats1/pos.size:1m:tBTCUSD:long/last 32 | string json = "[ 1500093780000, 15222.20717334 ]"; 33 | 34 | var stat = JsonConvert.DeserializeObject(json, new StatResultConverter()); 35 | 36 | Assert.AreEqual(1500093780000, stat.MTS); 37 | Assert.AreEqual(15222.20717334, stat.Value); 38 | } 39 | 40 | [TestMethod] 41 | public void StatsClientSectionLastTest() 42 | { 43 | var client = new BitfinexRestClient(); 44 | var stats = client.GetStats(Key.TotalOpenPosition, Symbol.BTCUSD, Side.Long, Section.Last, SortDirection.OldestToNewest); 45 | 46 | Assert.AreEqual(1, stats.Count); 47 | } 48 | 49 | [TestMethod] 50 | public void StatsClientSectionHistoricalTest() 51 | { 52 | var client = new BitfinexRestClient(); 53 | var stats = client.GetStats(Key.TotalOpenPosition, Symbol.BTCUSD, Side.Long, Section.Historical, SortDirection.OldestToNewest); 54 | 55 | Assert.IsTrue(stats.Count > 1); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Bitfinex/TradesClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Bitfinex.JsonConverters; 4 | using Bitfinex.Models; 5 | using RestSharp; 6 | using static System.String; 7 | using System; 8 | 9 | namespace Bitfinex 10 | { 11 | // All our Trade methods. 12 | 13 | public partial class BitfinexRestClient 14 | { 15 | /// 16 | /// Get pertinent details of trades, such as price, size and time. 17 | /// 18 | /// The symbol you want information about. 19 | /// List of trades 20 | public List GetTrades(string symbol) 21 | { 22 | return getTradesAsync(symbol).Result; 23 | } 24 | 25 | /// 26 | /// Get pertinent details of trades, such as price, size and time. 27 | /// 28 | /// The symbol you want information about. 29 | /// Number of records 30 | /// List of trades 31 | public List GetTrades(string symbol, int limit) 32 | { 33 | return getTradesAsync(symbol, limit).Result; 34 | } 35 | 36 | /// 37 | /// Get pertinent details of trades, such as price, size and time. 38 | /// 39 | /// The symbol you want information about. 40 | /// Number of records 41 | /// Millisecond start time 42 | /// List of trades 43 | public List GetTrades(string symbol, int limit, long start) 44 | { 45 | return getTradesAsync(symbol, limit, start).Result; 46 | } 47 | 48 | /// 49 | /// Get pertinent details of trades, such as price, size and time. 50 | /// 51 | /// The symbol you want information about. 52 | /// Number of records 53 | /// Millisecond start time 54 | /// Millisecond end time 55 | /// List of trades 56 | public List GetTrades(string symbol, int limit, long start, long end) 57 | { 58 | return getTradesAsync(symbol, limit, start, end).Result; 59 | } 60 | 61 | /// 62 | /// Get pertinent details of trades, such as price, size and time. 63 | /// 64 | /// The symbol you want information about. 65 | /// Number of records 66 | /// Millisecond start time 67 | /// Millisecond end time 68 | /// 69 | /// List of trades 70 | public List GetTrades(string symbol, int limit, long start, long end, SortDirection sortDirection) 71 | { 72 | return getTradesAsync(symbol, limit, start, end, sortDirection).Result; 73 | } 74 | 75 | /// 76 | /// Get pertinent details of trades, such as price, size and time. 77 | /// 78 | /// The symbol you want information about. 79 | /// List of trades 80 | public async Task> GetTradesAsync(string symbol) 81 | { 82 | return await getTradesAsync(symbol); 83 | } 84 | 85 | /// 86 | /// Get pertinent details of trades, such as price, size and time. 87 | /// 88 | /// The symbol you want information about. 89 | /// Number of records (default 120) 90 | /// List of trades 91 | public async Task> GetTradesAsync(string symbol, int limit) 92 | { 93 | return await getTradesAsync(symbol, limit); 94 | } 95 | 96 | /// 97 | /// Get pertinent details of trades, such as price, size and time. 98 | /// 99 | /// The symbol you want information about. 100 | /// Number of records (default 120) 101 | /// Millisecond start time (default 0) 102 | /// List of trades 103 | public async Task> GetTradesAsync(string symbol, int limit, long start) 104 | { 105 | return await getTradesAsync(symbol, limit, start); 106 | } 107 | 108 | /// 109 | /// Get pertinent details of trades, such as price, size and time. 110 | /// 111 | /// The symbol you want information about. 112 | /// Number of records (default 120) 113 | /// Millisecond start time (default 0) 114 | /// Millisecond end time (default 0) 115 | /// List of trades 116 | public async Task> GetTradesAsync(string symbol, int limit, long start, long end) 117 | { 118 | return await getTradesAsync(symbol, limit, start, end); 119 | } 120 | 121 | /// 122 | /// Get pertinent details of trades, such as price, size and time. 123 | /// 124 | /// The symbol you want information about. 125 | /// Number of records (default 120) 126 | /// Millisecond start time (default 0) 127 | /// Millisecond end time (default 0) 128 | /// Default new > old 129 | /// List of trades 130 | public async Task> GetTradesAsync(string symbol, int limit, long start, long end, SortDirection sortDirection) 131 | { 132 | return await getTradesAsync(symbol, limit, start, end, sortDirection); 133 | } 134 | 135 | private async Task> getTradesAsync(string symbol, int? limit = null, long? start = null, long? end = null, SortDirection? sortDirection = null) 136 | { 137 | var parameters = new List(); 138 | if (limit.GetValueOrDefault() != 0) parameters.Add("limit=" + limit); 139 | if (start.GetValueOrDefault() != 0) parameters.Add("start=" + start); 140 | if (end.GetValueOrDefault() != 0) parameters.Add("end=" + end); 141 | if (sortDirection != null) parameters.Add("sort=" + (int)sortDirection); 142 | 143 | string url = $"trades/{symbol}/hist"; 144 | if (parameters.Count > 0) url = url + "?" + Join("&", parameters.ToArray()); 145 | 146 | var request = new RestRequest(url, Method.GET); 147 | 148 | var response = await GetResponseAsync(request, CancellationToken); 149 | 150 | return (List)DeserializeObject>(response.Content, new TradesResultConverter()); 151 | } 152 | 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 10 | 11 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 12 | 13 | "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 14 | 15 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 16 | 17 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 18 | 19 | "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 20 | 21 | "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 22 | 23 | "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 24 | 25 | "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." 26 | 27 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 28 | 29 | 2. Grant of Copyright License. 30 | 31 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 32 | 33 | 3. Grant of Patent License. 34 | 35 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 36 | 37 | 4. Redistribution. 38 | 39 | You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 40 | 41 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 42 | You must cause any modified files to carry prominent notices stating that You changed the files; and 43 | You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 44 | If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 45 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 46 | 47 | 5. Submission of Contributions. 48 | 49 | Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 50 | 51 | 6. Trademarks. 52 | 53 | This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 54 | 55 | 7. Disclaimer of Warranty. 56 | 57 | Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 58 | 59 | 8. Limitation of Liability. 60 | 61 | In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 62 | 63 | 9. Accepting Warranty or Additional Liability. 64 | 65 | While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 66 | 67 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /Bitfinex.Tests/Models/BooksTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.JsonConverters; 4 | using Bitfinex.Models; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Newtonsoft.Json; 7 | 8 | namespace Bitfinex.Tests.Models 9 | { 10 | [TestClass] 11 | public class BooksTests 12 | { 13 | [TestMethod] 14 | public void BooksDeserializeTest1() 15 | { 16 | //GET: https://api.bitfinex.com/v2/book/fUSD/P0?len=5 17 | string json = "[ [ 8819908, 1499993669662, -42.48113687, 0.00026573, 2 ], [ 8819907, 1499993669637, -93.08533495, 0.00026571, 2 ], [ 8819906, 1499993669606, -80.23924126, 0.0002657, 2 ], [ 8819905, 1499993669580, -80.23924126, 0.0002657, 2 ], [ 8819904, 1499993669555, -90.44483913, 0.0002657, 2 ], [ 8819903, 1499993669508, -53.77420134, 0.0002657, 2 ], [ 8819902, 1499993669472, -53.77420134, 0.0002657, 2 ], [ 8819901, 1499993669408, -53.77420134, 0.0002657, 2 ], [ 8819900, 1499993669374, -2.6136619, 0.0002657, 2 ], [ 8819895, 1499993667107, -51.16053944, 0.0002657, 2 ], [ 8819894, 1499993667086, -53.77420134, 0.0002657, 2 ], [ 8819893, 1499993667057, -53.77420134, 0.0002657, 2 ], [ 8819892, 1499993667031, -2474.20793604, 0.0002657, 2 ], [ 8819891, 1499993667006, -53.77420134, 0.00026563, 2 ], [ 8819890, 1499993666980, -53.77420134, 0.00026563, 2 ], [ 8819889, 1499993666960, -53.77420134, 0.00026563, 2 ], [ 8819888, 1499993666933, -53.77420134, 0.00026563, 2 ], [ 8819887, 1499993666907, -53.77420134, 0.00026563, 2 ], [ 8819886, 1499993666887, -53.77420134, 0.00026563, 2 ], [ 8819885, 1499993666863, -53.77420134, 0.00026563, 2 ], [ 8819884, 1499993666843, -646.52363859, 0.00026563, 2 ], [ 8819883, 1499993666818, -4948.41587208, 0.00026563, 2 ], [ 8819882, 1499993666767, -87.03953651, 0.00026563, 2 ], [ 8819881, 1499993666727, -80.23924126, 0.00026562, 2 ], [ 8819880, 1499993666691, -80.23924126, 0.00026562, 2 ], [ 8819879, 1499993666658, -90.44483913, 0.00026562, 2 ], [ 8819878, 1499993666630, -53.77420134, 0.0002656, 2 ], [ 8819877, 1499993666605, -53.77420134, 0.0002656, 2 ], [ 8819876, 1499993666573, -80.23924126, 0.00026494, 2 ], [ 8819875, 1499993666536, -80.23924126, 0.00026494, 2 ], [ 8819874, 1499993666505, -4083.5268, 0.00026494, 2 ], [ 8819873, 1499993666478, -50, 0.0002649, 2 ], [ 8819872, 1499993666447, -1768.6234, 0.0002648, 2 ], [ 8819871, 1499993666416, -98.37, 0.0002648, 3 ], [ 8819870, 1499993666371, -169.69, 0.0002648, 3 ], [ 8819869, 1499993666311, -80.23924126, 0.0002647, 2 ], [ 8819868, 1499993666288, -90.44483913, 0.0002647, 2 ], [ 8819867, 1499993666256, -2474.20793604, 0.0002647, 2 ], [ 8819866, 1499993666222, -5081.18275562, 0.00026468, 2 ], [ 8819865, 1499993666200, -11078.18090284, 0.00026468, 2 ], [ 8819864, 1499993666152, -900.84877392, 0.00026368, 2 ], [ 8819839, 1499993661552, -24.08470096, 0.00026368, 2 ], [ 8819838, 1499993661481, -73.62422513, 0.00026368, 2 ], [ 8819832, 1499993655549, -20561.66978856, 0.00026468, 2 ], [ 8819831, 1499993654708, -14.1942157, 0.00026468, 2 ], [ 8819829, 1499993654659, -2.45249997, 0.00022719, 2 ], [ 8819827, 1499993653789, -47.54750003, 0.00022719, 2 ], [ 8819826, 1499993653730, -0.215336, 0.00026468, 2 ], [ 8819825, 1499993653665, -6163.58260527, 0.00026468, 2 ], [ 8819824, 1499993653601, -1962.84, 0.00026467, 2 ], [ 8819823, 1499993653567, -1326.7468018, 0.00026465, 2 ], [ 8819822, 1499993653459, -56.90229132, 0.00026387, 2 ], [ 8819821, 1499993653411, -237.783, 0.00026387, 2 ], [ 8819820, 1499993653372, -111.95655804, 0.00026368, 2 ], [ 8819819, 1499993653337, -80.23924126, 0.0002617, 2 ], [ 8819818, 1499993653277, -596.14230575, 0.0002617, 2 ], [ 8819817, 1499993653250, -80.23924126, 0.00023966, 2 ], [ 8819815, 1499993653196, -80.23924126, 0.00023966, 2 ], [ 8819814, 1499993653159, -80.23924126, 0.00023966, 2 ], [ 8819813, 1499993653100, -80.23924126, 0.00023966, 2 ], [ 8819812, 1499993653074, -80.23924126, 0.00023966, 2 ], [ 8819811, 1499993652976, -80.23924126, 0.00023966, 2 ], [ 8819810, 1499993652937, -451, 0.000236, 2 ], [ 8819809, 1499993652914, -56.90229132, 0.0002296, 2 ], [ 8819808, 1499993652888, -56.24275274, 0.0002296, 2 ], [ 8819807, 1499993652857, -56.24275274, 0.0002296, 2 ], [ 8819806, 1499993652812, -90.44483913, 0.00022749, 2 ], [ 8819805, 1499993652734, -1882.80746053, 0.00022749, 2 ], [ 8819804, 1499993652652, -85.14923868, 0.0002274, 2 ], [ 8819803, 1499993652628, -1408.82154882, 0.0002273, 2 ], [ 8819802, 1499993652569, -1408.82154882, 0.0002273, 2 ], [ 8819801, 1499993652510, -599.4112884, 0.0002273, 2 ], [ 8819799, 1499993652458, -599.4112884, 0.0002273, 2 ], [ 8819798, 1499993652356, -90.44483913, 0.0002273, 2 ], [ 8819797, 1499993652294, -4287.06443826, 0.0002273, 2 ], [ 8819796, 1499993651901, -779.58632982, 0.0002273, 2 ], [ 8819775, 1499993648738, -86.4999999, 0.0002273, 2 ], [ 8819773, 1499993647636, -215.50975942, 0.0002273, 2 ], [ 8819772, 1499993646194, -29.67599058, 0.0002273, 2 ], [ 8819765, 1499993643036, -54.1290761, 0.0002273, 2 ], [ 8819759, 1499993639396, -1.66913336, 0.0002273, 2 ], [ 8819756, 1499993638220, -179.39355176, 0.0002273, 2 ], [ 8819755, 1499993638152, -50, 0.0002273, 2 ], [ 8819754, 1499993638118, -50, 0.0002273, 2 ], [ 8819753, 1499993638081, -68.79399651, 0.0002273, 2 ], [ 8819752, 1499993635466, -190.02840302, 0.0002273, 2 ], [ 8819751, 1499993633585, -0.19886031, 0.0002273, 2 ], [ 8819750, 1499993632156, -44.3313754, 0.0002273, 2 ], [ 8819748, 1499993628217, -15.38736476, 0.0002273, 2 ], [ 8819747, 1499993628140, -65.45692284, 0.0002271, 2 ], [ 8819746, 1499993628040, -57.25490182, 0.0002271, 2 ], [ 8819745, 1499993625767, -25.019, 0.0002271, 2 ], [ 8819744, 1499993624420, -4.75883443, 0.0002271, 2 ], [ 8819743, 1499993622485, -753.56998339, 0.0002271, 2 ], [ 8819742, 1499993621593, -568.21882918, 0.0002271, 2 ], [ 8819741, 1499993621541, -599.4112884, 0.0002271, 2 ], [ 8819740, 1499993621484, -110.97509029, 0.0002271, 2 ], [ 8819739, 1499993621416, -50, 0.00022492, 2 ], [ 8819738, 1499993621357, -50, 0.00022481, 2 ], [ 8819737, 1499993621272, -602.16479213, 0.00022465, 2 ], [ 8819736, 1499993621192, -5.3639181, 0.00022465, 2 ], [ 8819732, 1499993584813, -50, 0.00022465, 2 ], [ 8819731, 1499993353283, -19, 0.0002659, 2 ], [ 8819729, 1499993352687, -967.61447872, 0.0002659, 2 ], [ 8819727, 1499993352105, -1167.98962257, 0.0002659, 2 ], [ 8819725, 1499993351249, -16023.36348933, 0.0002659, 2 ], [ 8819724, 1499993351230, -2098.64941318, 0.0002659, 2 ], [ 8819719, 1499993347667, -71.1836148, 0.0002659, 2 ], [ 8819718, 1499993347647, -135.7293452, 0.0002658, 2 ], [ 8819717, 1499993347624, -509.22367437, 0.0002658, 2 ], [ 8819712, 1499993346579, -52.37534993, 0.0002658, 2 ], [ 8819708, 1499993343496, -0.65331699, 0.0002658, 2 ], [ 8819707, 1499993343468, -2530.78440774, 0.0002658, 2 ], [ 8819706, 1499993343446, -1263.84, 0.0002658, 2 ], [ 8819705, 1499993343424, -120.35886189, 0.000265, 2 ], [ 8819704, 1499993343403, -120.35886189, 0.000265, 2 ], [ 8819703, 1499993343380, -120.35886189, 0.000265, 2 ], [ 8819702, 1499993343358, -147.42764988, 0.000265, 2 ], [ 8819701, 1499993342997, -1.30474549, 0.000265, 2 ], [ 8819697, 1499993341704, -7127.22537711, 0.000265, 2 ]]"; 18 | 19 | // TO-DO: Broken endpoint? 20 | 21 | } 22 | 23 | [TestMethod] 24 | public void BooksDeserializeTest2() 25 | { 26 | //GET: https://api.bitfinex.com/v2/book/tBTCUSD/P0?len=5 27 | string json = "[ [ 2317.9,2,3.54219284 ],[ 2317.1,1,0.9589 ],[ 2317,1,2.965041 ],[ 2315.2,1,7.64043703 ],[ 2315,2,24.62799232 ],[ 2318,4,-4.18890282 ],[ 2318.6,1,-1.8 ],[ 2318.9,1,-1.0761 ],[ 2319,2,-14 ],[ 2319.4,1,-2.79672805 ] ]"; 28 | 29 | var books = JsonConvert.DeserializeObject>(json, new BooksResultConverter()); 30 | 31 | Assert.AreEqual(10, books.Count); 32 | 33 | var book = books[0]; 34 | 35 | Assert.AreEqual(3.54219284, book.Amount); 36 | Assert.AreEqual(2, book.Count); 37 | Assert.AreEqual(2317.9, book.Price); 38 | } 39 | 40 | [TestMethod] 41 | public void BooksClientTest() 42 | { 43 | var client = new BitfinexRestClient(); 44 | var books = client.GetBooks("tBTCUSD", Precision.P0, 5); 45 | 46 | Assert.AreEqual(10, books.Count); 47 | } 48 | 49 | [TestMethod] 50 | public void BooksClientWrongSymbolTest() 51 | { 52 | try 53 | { 54 | var client = new BitfinexRestClient(); 55 | client.GetBooks("fUSD", Precision.P0, 5); 56 | } 57 | catch (Exception ex) 58 | { 59 | if (ex.InnerException != null) Assert.AreEqual(ex.InnerException.Message, "(10020) symbol: invalid"); 60 | } 61 | } 62 | 63 | [TestMethod] 64 | public void BooksClientIncorrectEndpointTest() 65 | { 66 | try 67 | { 68 | var client = new BitfinexRestClient { BaseUrl = "https://api.bitfinexf.com/v2" }; 69 | 70 | client.GetBooks("fUSD", Precision.P0, 5); 71 | } 72 | catch (Exception ex) 73 | { 74 | if (ex.InnerException != null) 75 | Assert.AreEqual(ex.InnerException.Message, 76 | "The remote name could not be resolved: 'api.bitfinexf.com'"); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Bitfinex.Tests/Models/CandlesTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Bitfinex.JsonConverters; 3 | using Bitfinex.Models; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using Newtonsoft.Json; 6 | 7 | namespace Bitfinex.Tests.Models 8 | { 9 | [TestClass] 10 | public class CandlesTests 11 | { 12 | [TestMethod] 13 | public void CandlesDeserializeTest1() 14 | { 15 | //GET: https://api.bitfinex.com/v2/candles/trade:1m:tBTCUSD/hist 16 | string json = "[ [ 1500162180000, 1995.7, 1987.2, 1995.7, 1987.2, 22.97632724 ], [ 1500162120000, 1995, 1995.7, 1997, 1994.5, 17.4851571 ], [ 1500162060000, 1999.7, 1996.86868653, 1999.7, 1995, 34.40969878 ], [ 1500162000000, 1997.9, 1999.6, 2000.4, 1997.8, 6.03225561 ], [ 1500161940000, 1996.4, 1998, 1998, 1996.2, 3.79828954 ], [ 1500161880000, 1995.6, 1995.9, 1997.8964698, 1995.4, 25.90021105 ], [ 1500161820000, 1983.6, 1994.6, 1995.72670513, 1983.6, 50.64021199 ], [ 1500161760000, 1982.8, 1983.5, 1984.9, 1980, 70.17040888 ], [ 1500161700000, 1981.5, 1981.5, 1986.3, 1980, 122.59006551 ], [ 1500161640000, 1989.9, 1981.5, 1990, 1979.1, 124.62594331 ], [ 1500161580000, 2002, 1989.9, 2002, 1985.2, 467.48905936 ], [ 1500161520000, 2005.7, 2001.9, 2006, 2001.9, 4.89232837 ], [ 1500161460000, 2007, 2005.9, 2007.6, 2005.9, 12.27400103 ], [ 1500161400000, 2011, 2007, 2011.1, 2007, 3.67709528 ], [ 1500161340000, 2016.8, 2011, 2016.8, 2011, 20.01826389 ], [ 1500161280000, 2016.8, 2016.8, 2016.9, 2016.8, 5.97632501 ], [ 1500161220000, 2020, 2017, 2020, 2016.5, 3.63460356 ], [ 1500161160000, 2019.5, 2016.62496486, 2020.4, 2016.05397415, 11.93354221 ], [ 1500161100000, 2016.1, 2019.4, 2020.9, 2016.1, 9.30303567 ], [ 1500161040000, 2018, 2019.2, 2019.5, 2015.02619089, 4.079675 ], [ 1500160980000, 2020.05090907, 2015.59718159, 2020.62189978, 2015.59718159, 17.7406763 ], [ 1500160920000, 2020.7, 2020.05090907, 2023.1, 2020, 37.96354923 ], [ 1500160860000, 2026.7, 2020.7, 2026.7, 2020.7, 17.33498322 ], [ 1500160800000, 2027.9, 2028, 2029.1, 2026, 35.88429581 ], [ 1500160740000, 2032.8, 2030, 2032.8, 2029.2, 5.13418676 ], [ 1500160680000, 2034.9, 2030.4, 2034.9, 2030.2, 6.09735201 ], [ 1500160620000, 2034.9, 2034.8, 2035, 2034.8, 2.79991912 ], [ 1500160560000, 2033.8, 2034.8, 2036, 2033.7, 29.46490015 ], [ 1500160500000, 2036.9, 2036.1, 2036.9, 2036.1, 3.8529104 ], [ 1500160440000, 2037.6, 2041.2, 2041.2, 2037.6, 1.70119642 ], [ 1500160380000, 2039.9, 2039.4, 2044.6, 2039.3, 3.1983107 ], [ 1500160320000, 2042.6, 2043.3, 2043.5, 2038.5, 10.08400001 ], [ 1500160260000, 2035.8, 2037.1, 2042.66214091, 2033.2, 6.70065163 ], [ 1500160200000, 2035.8, 2032.5, 2036, 2032.5, 9.87 ], [ 1500160140000, 2039.8, 2036.2, 2039.8, 2035.8, 8.48168178 ], [ 1500160080000, 2038.6, 2039.8, 2039.8, 2038.5, 2.97000969 ], [ 1500160020000, 2042.4, 2038.6, 2045.8, 2037.6, 0.27645094 ], [ 1500159960000, 2046.4, 2042.1, 2046.4, 2042, 3.53193462 ], [ 1500159900000, 2045.7, 2046.8, 2046.9, 2045.7, 3.26026574 ], [ 1500159840000, 2046.9, 2047.8, 2048, 2046.6, 2.53834372 ], [ 1500159780000, 2046.9, 2046.9, 2047, 2045.3, 9.43997543 ], [ 1500159720000, 2045.8, 2046.8, 2050, 2045.5, 21.04432284 ], [ 1500159660000, 2040.8, 2044.4, 2050.1, 2040.7, 99.67203311 ], [ 1500159600000, 2032, 2036.9, 2036.9, 2031.81331756, 12.02780761 ], [ 1500159540000, 2027.9, 2032, 2032.6, 2027.6, 7.1549663 ], [ 1500159480000, 2027.9, 2027.1, 2027.9, 2027.1, 0.2233022 ], [ 1500159420000, 2027.01699565, 2027.9, 2028.9, 2026.7, 2.72581875 ], [ 1500159360000, 2031.3, 2026.10341053, 2034.7, 2026.10341053, 7.68789213 ], [ 1500159300000, 2031.6, 2031.2, 2034.8, 2027.5, 7.68397458 ], [ 1500159240000, 2032.61270454, 2031.9, 2035, 2031, 4.34505748 ], [ 1500159180000, 2037, 2032.4985064, 2037, 2032.4985064, 9.84218333 ], [ 1500159120000, 2038, 2036.8, 2038.1, 2035.2, 8.0394852 ], [ 1500159060000, 2038, 2038, 2038, 2038, 0.03557219 ], [ 1500159000000, 2041.9, 2039.5, 2041.9, 2038.4, 25.13458134 ], [ 1500158940000, 2042.1, 2042, 2042.1, 2042, 4.26789531 ], [ 1500158880000, 2043.3, 2043.3, 2043.3, 2043.3, 0.03698901 ], [ 1500158820000, 2042, 2043.2, 2043.2, 2042, 0.44716155 ], [ 1500158760000, 2043.2, 2043.2, 2043.3, 2042, 0.08153407 ], [ 1500158700000, 2040.8, 2043.1, 2047, 2040.8, 7.16597568 ], [ 1500158640000, 2040.2, 2042.5, 2042.5, 2038.4, 3.540761 ], [ 1500158580000, 2044.5, 2038.5, 2044.5, 2036.1528469, 12.97337617 ], [ 1500158520000, 2046.5, 2040.83497066, 2046.5, 2040.83497066, 26.10096069 ], [ 1500158460000, 2048.1, 2046.6, 2048.1, 2046.5, 4.06512445 ], [ 1500158400000, 2051.6, 2048.1, 2051.6, 2048.1, 0.90595857 ], [ 1500158340000, 2055.2, 2053.9, 2055.2, 2053.9, 1.62993384 ], [ 1500158280000, 2059, 2055.2, 2059, 2055.2, 4.92301136 ], [ 1500158220000, 2061, 2059.9, 2061, 2059.5, 10.994915 ], [ 1500158160000, 2061.3, 2063.9, 2063.9, 2061.2, 7.07495719 ], [ 1500158100000, 2056.1, 2061.3, 2061.4, 2056.1, 6.92721002 ], [ 1500158040000, 2057.1, 2057, 2057.8, 2057, 3.53238155 ], [ 1500157980000, 2058.1, 2057.1, 2058.2, 2057.1, 0.56829621 ], [ 1500157920000, 2054.1, 2057.9, 2057.9, 2054.1, 13.56914211 ], [ 1500157860000, 2048, 2052.9, 2064, 2046.8, 75.09458677 ], [ 1500157800000, 2049.5, 2048, 2049.5, 2048, 0.51927813 ], [ 1500157740000, 2044.9, 2049.3, 2049.3, 2044.8, 6.26535979 ], [ 1500157680000, 2039.7, 2043.8, 2043.8, 2039.7, 5.3953595 ], [ 1500157620000, 2039.8, 2039.7, 2039.8, 2038.3, 4.73073907 ], [ 1500157560000, 2042.31954649, 2039.9, 2045, 2039.8, 4.10262838 ], [ 1500157500000, 2046.6, 2042.31954649, 2046.6, 2042.31954649, 2.16118793 ], [ 1500157440000, 2051, 2046.6, 2051, 2046.6, 3.20495404 ], [ 1500157380000, 2051.6, 2051.6, 2051.6, 2051.6, 0.03023163 ], [ 1500157320000, 2056.2, 2051.6, 2056.2, 2051.6, 9.14784316 ], [ 1500157260000, 2056, 2053.9, 2056.4, 2053.9, 19.1085068 ], [ 1500157200000, 2058.9, 2059.7, 2059.7, 2056, 1.2736754 ], [ 1500157140000, 2058, 2059.7, 2059.7, 2057.6, 16.09856437 ], [ 1500157080000, 2055, 2057.6, 2058, 2054.3, 25.57670276 ], [ 1500157020000, 2052.8, 2054.9955401, 2055.2, 2051.9, 24.53272347 ], [ 1500156960000, 2053.4, 2053.2, 2053.5, 2052.8, 1.306931 ], [ 1500156900000, 2049.3, 2052.8, 2054, 2049.3, 6.61917221 ], [ 1500156840000, 2048.9, 2049.4, 2049.4, 2046.6, 1.29606497 ], [ 1500156780000, 2053, 2046.8, 2053.2, 2046.8, 12.69946234 ], [ 1500156720000, 2056.3, 2054.1, 2058.3, 2052.7, 43.78514919 ], [ 1500156660000, 2055.3, 2057.8, 2058, 2052.2, 60.36936131 ], [ 1500156600000, 2053.3, 2055.3, 2059.8, 2053.1, 9.93483066 ], [ 1500156540000, 2043.6, 2058.5, 2058.5, 2043.57572604, 40.15689708 ], [ 1500156480000, 2035.4, 2043.5, 2046.5, 2035.4, 30.94043752 ], [ 1500156420000, 2028.9, 2035.2, 2039.8, 2028.9, 24.75357457 ], [ 1500156360000, 2027.9, 2028.8, 2028.8, 2027, 6.76810539 ], [ 1500156300000, 2024.9, 2028, 2028, 2023.9, 46.63302101 ], [ 1500156240000, 2021.5, 2024, 2025.6, 2021.5, 9.81131154 ], [ 1500156180000, 2030.9, 2023.6, 2031, 2022.5, 99.04275051 ], [ 1500156120000, 2028, 2030.9, 2030.9, 2026.67440123, 23.13572439 ], [ 1500156060000, 2033.1, 2028.8, 2034.5, 2028.8, 118.38653001 ], [ 1500156000000, 2033.5, 2033.1, 2034.6, 2033, 126.50116941 ], [ 1500155940000, 2033, 2033, 2034.2, 2033, 1.15005113 ], [ 1500155880000, 2035, 2033, 2037.9, 2033, 6.73203763 ], [ 1500155820000, 2040, 2035.3, 2043.1, 2035.3, 116.30081003 ], [ 1500155760000, 2032.1, 2040, 2040.03558368, 2032.1, 64.09353059 ], [ 1500155700000, 2036.9, 2032.1, 2036.9, 2032.1, 15.56460969 ], [ 1500155640000, 2044, 2035.9, 2046.1, 2035.9, 21.29541685 ], [ 1500155580000, 2056, 2044, 2056, 2044, 42.63603848 ], [ 1500155520000, 2060, 2056, 2060, 2056, 6.48182999 ], [ 1500155460000, 2060, 2060, 2060.2, 2059.7, 32.36917066 ], [ 1500155400000, 2056.1, 2060, 2060.1, 2055, 217.46795998 ], [ 1500155340000, 2056.2, 2056, 2056.2, 2056, 3.73433892 ], [ 1500155280000, 2056.1, 2056.1, 2056.3, 2056, 13.37990461 ], [ 1500155220000, 2055.3, 2056.1, 2056.7, 2055, 11.36517902 ], [ 1500155160000, 2052, 2055.1, 2055.1, 2051.8, 27.46606242 ], [ 1500155100000, 2050.8, 2051.8, 2055, 2050.5, 12.07131499 ], [ 1500155040000, 2048.3, 2050.9, 2050.9, 2046, 76.65404401 ] ]"; 17 | 18 | var candles = JsonConvert.DeserializeObject>(json, new CandlesResultConverter()); 19 | 20 | Assert.AreEqual(120, candles.Count); 21 | 22 | var candle = candles[0]; 23 | 24 | Assert.AreEqual(1500162180000, candle.MTS); 25 | Assert.AreEqual(1995.7, candle.Open); 26 | Assert.AreEqual(1987.2, candle.Close); 27 | Assert.AreEqual(1995.7, candle.High); 28 | Assert.AreEqual(1987.2, candle.Low); 29 | Assert.AreEqual(22.97632724, candle.Volume); 30 | } 31 | 32 | [TestMethod] 33 | public void CandlesDeserializeTest2() 34 | { 35 | //GET: https://api.bitfinex.com/v2/candles/trade:1m:tBTCUSD/last 36 | string json = "[ 1500162180000, 1995.7, 1995.7, 1995.7, 1995.7, 1.32939032 ]"; 37 | 38 | var candle = JsonConvert.DeserializeObject(json, new CandleResultConverter()); 39 | 40 | Assert.AreEqual(1500162180000, candle.MTS); 41 | Assert.AreEqual(1995.7, candle.Open); 42 | Assert.AreEqual(1995.7, candle.Close); 43 | Assert.AreEqual(1995.7, candle.High); 44 | Assert.AreEqual(1995.7, candle.Low); 45 | Assert.AreEqual(1.32939032, candle.Volume); 46 | } 47 | 48 | [TestMethod] 49 | public void CandlesClientSectionLastTest() 50 | { 51 | var client = new BitfinexRestClient(); 52 | var candles = client.GetCandles(TimeFrame.Minute, Symbol.BTCUSD, Section.Last); 53 | 54 | Assert.AreEqual(1, candles.Count); 55 | } 56 | 57 | [TestMethod] 58 | public void CandlesClientSectionHistoricalTest() 59 | { 60 | var client = new BitfinexRestClient(); 61 | var candles = client.GetCandles(TimeFrame.Minute, Symbol.BTCUSD, Section.Historical); 62 | 63 | Assert.IsTrue(candles.Count > 1); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Bitfinex/CandlesClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Bitfinex.JsonConverters; 5 | using Bitfinex.Models; 6 | using RestSharp; 7 | using static System.String; 8 | 9 | namespace Bitfinex 10 | { 11 | // All our Stats methods. 12 | 13 | public partial class BitfinexRestClient 14 | { 15 | /// 16 | /// Get charting candle info 17 | /// 18 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 19 | /// The symbol you want information about. 20 | /// Available values: "last", "hist" 21 | /// A list of candle information 22 | public List GetCandles(TimeFrame timeframe, Symbol symbol, Section section) 23 | { 24 | return getCandlesAsync(timeframe, symbol, section).Result; 25 | } 26 | 27 | /// 28 | /// Get charting candle info 29 | /// 30 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 31 | /// The symbol you want information about. 32 | /// Available values: "last", "hist" 33 | /// Number of candles requested 34 | /// A list of candle information 35 | public List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit) 36 | { 37 | return getCandlesAsync(timeframe, symbol, section, limit).Result; 38 | } 39 | 40 | /// 41 | /// Get charting candle info 42 | /// 43 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 44 | /// The symbol you want information about. 45 | /// Available values: "last", "hist" 46 | /// Number of candles requested 47 | /// Filter start (ms) 48 | /// A list of candle information 49 | public List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start) 50 | { 51 | return getCandlesAsync(timeframe, symbol, section, limit, start).Result; 52 | } 53 | 54 | /// 55 | /// Get charting candle info 56 | /// 57 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 58 | /// The symbol you want information about. 59 | /// Available values: "last", "hist" 60 | /// Number of candles requested 61 | /// Filter start (ms) 62 | /// Filter end (ms) 63 | /// A list of candle information 64 | public List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end) 65 | { 66 | return getCandlesAsync(timeframe, symbol, section, limit, start, end).Result; 67 | } 68 | 69 | /// 70 | /// Get charting candle info 71 | /// 72 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 73 | /// The symbol you want information about. 74 | /// Available values: "last", "hist" 75 | /// Number of candles requested 76 | /// Filter start (ms) 77 | /// Filter end (ms) 78 | /// Default new > old 79 | /// A list of candle information 80 | public List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end, SortDirection sortDirection) 81 | { 82 | // TO-DO: The spec says that the start and end are string. We are handling as ints. 83 | 84 | return getCandlesAsync(timeframe, symbol, section, limit, start, end, sortDirection).Result; 85 | } 86 | 87 | /// 88 | /// Get charting candle info 89 | /// 90 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 91 | /// The symbol you want information about. 92 | /// Available values: "last", "hist" 93 | /// A list of candle information 94 | public async Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section) 95 | { 96 | return await getCandlesAsync(timeframe, symbol, section); 97 | } 98 | 99 | /// 100 | /// Get charting candle info 101 | /// 102 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 103 | /// The symbol you want information about. 104 | /// Available values: "last", "hist" 105 | /// Number of candles requested 106 | /// A list of candle information 107 | public async Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit) 108 | { 109 | return await getCandlesAsync(timeframe, symbol, section, limit); 110 | } 111 | 112 | /// 113 | /// Get charting candle info 114 | /// 115 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 116 | /// The symbol you want information about. 117 | /// Available values: "last", "hist" 118 | /// Number of candles requested 119 | /// Filter start (ms) 120 | /// A list of candle information 121 | public async Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start) 122 | { 123 | return await getCandlesAsync(timeframe, symbol, section, limit, start); 124 | } 125 | 126 | /// 127 | /// Get charting candle info 128 | /// 129 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 130 | /// The symbol you want information about. 131 | /// Available values: "last", "hist" 132 | /// Number of candles requested 133 | /// Filter start (ms) 134 | /// Filter end (ms) 135 | /// A list of candle information 136 | public async Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end) 137 | { 138 | return await getCandlesAsync(timeframe, symbol, section, limit, start, end); 139 | } 140 | 141 | /// 142 | /// Get charting candle info 143 | /// 144 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 145 | /// The symbol you want information about. 146 | /// Available values: "last", "hist" 147 | /// Number of candles requested 148 | /// Filter start (ms) 149 | /// Filter end (ms) 150 | /// Default new > old 151 | /// A list of candle information 152 | public async Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end, SortDirection sortDirection) 153 | { 154 | return await getCandlesAsync(timeframe, symbol, section, limit, start, end, sortDirection); 155 | } 156 | 157 | private async Task> getCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int? limit = null, long? start = null, long? end = null, SortDirection? sortDirection = null) 158 | { 159 | var parameters = new List(); 160 | if (limit.GetValueOrDefault() != 0) parameters.Add("limit=" + limit); 161 | if (start.GetValueOrDefault() != 0) parameters.Add("start=" + start); 162 | if (end.GetValueOrDefault() != 0) parameters.Add("end=" + end); 163 | if (sortDirection != null) parameters.Add("sort=" + (int)sortDirection); 164 | 165 | string url = $"candles/trade:{timeframe}:{(TradeSymbol)symbol}/{section}"; 166 | if (parameters.Count > 0) url = url + "?" + Join("&", parameters.ToArray()); 167 | 168 | var request = new RestRequest(url, Method.GET); 169 | 170 | var response = await GetResponseAsync(request, CancellationToken); 171 | 172 | // We could have recieved a single candle. 173 | try 174 | { 175 | var candle = (Candle)DeserializeObject(response.Content, new CandleResultConverter()); 176 | if (candle != null) return new List() { candle }; 177 | } 178 | catch (Exception) 179 | { 180 | // ignored 181 | } 182 | 183 | return (List)DeserializeObject>(response.Content, new CandlesResultConverter()); 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /Bitfinex.Tests/Models/TradesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Bitfinex.JsonConverters; 4 | using Bitfinex.Models; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Newtonsoft.Json; 7 | 8 | namespace Bitfinex.Tests.Models 9 | { 10 | [TestClass] 11 | public class TradesTests 12 | { 13 | [TestMethod] 14 | public void TradesDeserializeTest1() 15 | { 16 | //GET: https://api.bitfinex.com/v2/trades/fUSD/hist 17 | string json = "[ [ 8819908, 1499993669662, -42.48113687, 0.00026573, 2 ], [ 8819907, 1499993669637, -93.08533495, 0.00026571, 2 ], [ 8819906, 1499993669606, -80.23924126, 0.0002657, 2 ], [ 8819905, 1499993669580, -80.23924126, 0.0002657, 2 ], [ 8819904, 1499993669555, -90.44483913, 0.0002657, 2 ], [ 8819903, 1499993669508, -53.77420134, 0.0002657, 2 ], [ 8819902, 1499993669472, -53.77420134, 0.0002657, 2 ], [ 8819901, 1499993669408, -53.77420134, 0.0002657, 2 ], [ 8819900, 1499993669374, -2.6136619, 0.0002657, 2 ], [ 8819895, 1499993667107, -51.16053944, 0.0002657, 2 ], [ 8819894, 1499993667086, -53.77420134, 0.0002657, 2 ], [ 8819893, 1499993667057, -53.77420134, 0.0002657, 2 ], [ 8819892, 1499993667031, -2474.20793604, 0.0002657, 2 ], [ 8819891, 1499993667006, -53.77420134, 0.00026563, 2 ], [ 8819890, 1499993666980, -53.77420134, 0.00026563, 2 ], [ 8819889, 1499993666960, -53.77420134, 0.00026563, 2 ], [ 8819888, 1499993666933, -53.77420134, 0.00026563, 2 ], [ 8819887, 1499993666907, -53.77420134, 0.00026563, 2 ], [ 8819886, 1499993666887, -53.77420134, 0.00026563, 2 ], [ 8819885, 1499993666863, -53.77420134, 0.00026563, 2 ], [ 8819884, 1499993666843, -646.52363859, 0.00026563, 2 ], [ 8819883, 1499993666818, -4948.41587208, 0.00026563, 2 ], [ 8819882, 1499993666767, -87.03953651, 0.00026563, 2 ], [ 8819881, 1499993666727, -80.23924126, 0.00026562, 2 ], [ 8819880, 1499993666691, -80.23924126, 0.00026562, 2 ], [ 8819879, 1499993666658, -90.44483913, 0.00026562, 2 ], [ 8819878, 1499993666630, -53.77420134, 0.0002656, 2 ], [ 8819877, 1499993666605, -53.77420134, 0.0002656, 2 ], [ 8819876, 1499993666573, -80.23924126, 0.00026494, 2 ], [ 8819875, 1499993666536, -80.23924126, 0.00026494, 2 ], [ 8819874, 1499993666505, -4083.5268, 0.00026494, 2 ], [ 8819873, 1499993666478, -50, 0.0002649, 2 ], [ 8819872, 1499993666447, -1768.6234, 0.0002648, 2 ], [ 8819871, 1499993666416, -98.37, 0.0002648, 3 ], [ 8819870, 1499993666371, -169.69, 0.0002648, 3 ], [ 8819869, 1499993666311, -80.23924126, 0.0002647, 2 ], [ 8819868, 1499993666288, -90.44483913, 0.0002647, 2 ], [ 8819867, 1499993666256, -2474.20793604, 0.0002647, 2 ], [ 8819866, 1499993666222, -5081.18275562, 0.00026468, 2 ], [ 8819865, 1499993666200, -11078.18090284, 0.00026468, 2 ], [ 8819864, 1499993666152, -900.84877392, 0.00026368, 2 ], [ 8819839, 1499993661552, -24.08470096, 0.00026368, 2 ], [ 8819838, 1499993661481, -73.62422513, 0.00026368, 2 ], [ 8819832, 1499993655549, -20561.66978856, 0.00026468, 2 ], [ 8819831, 1499993654708, -14.1942157, 0.00026468, 2 ], [ 8819829, 1499993654659, -2.45249997, 0.00022719, 2 ], [ 8819827, 1499993653789, -47.54750003, 0.00022719, 2 ], [ 8819826, 1499993653730, -0.215336, 0.00026468, 2 ], [ 8819825, 1499993653665, -6163.58260527, 0.00026468, 2 ], [ 8819824, 1499993653601, -1962.84, 0.00026467, 2 ], [ 8819823, 1499993653567, -1326.7468018, 0.00026465, 2 ], [ 8819822, 1499993653459, -56.90229132, 0.00026387, 2 ], [ 8819821, 1499993653411, -237.783, 0.00026387, 2 ], [ 8819820, 1499993653372, -111.95655804, 0.00026368, 2 ], [ 8819819, 1499993653337, -80.23924126, 0.0002617, 2 ], [ 8819818, 1499993653277, -596.14230575, 0.0002617, 2 ], [ 8819817, 1499993653250, -80.23924126, 0.00023966, 2 ], [ 8819815, 1499993653196, -80.23924126, 0.00023966, 2 ], [ 8819814, 1499993653159, -80.23924126, 0.00023966, 2 ], [ 8819813, 1499993653100, -80.23924126, 0.00023966, 2 ], [ 8819812, 1499993653074, -80.23924126, 0.00023966, 2 ], [ 8819811, 1499993652976, -80.23924126, 0.00023966, 2 ], [ 8819810, 1499993652937, -451, 0.000236, 2 ], [ 8819809, 1499993652914, -56.90229132, 0.0002296, 2 ], [ 8819808, 1499993652888, -56.24275274, 0.0002296, 2 ], [ 8819807, 1499993652857, -56.24275274, 0.0002296, 2 ], [ 8819806, 1499993652812, -90.44483913, 0.00022749, 2 ], [ 8819805, 1499993652734, -1882.80746053, 0.00022749, 2 ], [ 8819804, 1499993652652, -85.14923868, 0.0002274, 2 ], [ 8819803, 1499993652628, -1408.82154882, 0.0002273, 2 ], [ 8819802, 1499993652569, -1408.82154882, 0.0002273, 2 ], [ 8819801, 1499993652510, -599.4112884, 0.0002273, 2 ], [ 8819799, 1499993652458, -599.4112884, 0.0002273, 2 ], [ 8819798, 1499993652356, -90.44483913, 0.0002273, 2 ], [ 8819797, 1499993652294, -4287.06443826, 0.0002273, 2 ], [ 8819796, 1499993651901, -779.58632982, 0.0002273, 2 ], [ 8819775, 1499993648738, -86.4999999, 0.0002273, 2 ], [ 8819773, 1499993647636, -215.50975942, 0.0002273, 2 ], [ 8819772, 1499993646194, -29.67599058, 0.0002273, 2 ], [ 8819765, 1499993643036, -54.1290761, 0.0002273, 2 ], [ 8819759, 1499993639396, -1.66913336, 0.0002273, 2 ], [ 8819756, 1499993638220, -179.39355176, 0.0002273, 2 ], [ 8819755, 1499993638152, -50, 0.0002273, 2 ], [ 8819754, 1499993638118, -50, 0.0002273, 2 ], [ 8819753, 1499993638081, -68.79399651, 0.0002273, 2 ], [ 8819752, 1499993635466, -190.02840302, 0.0002273, 2 ], [ 8819751, 1499993633585, -0.19886031, 0.0002273, 2 ], [ 8819750, 1499993632156, -44.3313754, 0.0002273, 2 ], [ 8819748, 1499993628217, -15.38736476, 0.0002273, 2 ], [ 8819747, 1499993628140, -65.45692284, 0.0002271, 2 ], [ 8819746, 1499993628040, -57.25490182, 0.0002271, 2 ], [ 8819745, 1499993625767, -25.019, 0.0002271, 2 ], [ 8819744, 1499993624420, -4.75883443, 0.0002271, 2 ], [ 8819743, 1499993622485, -753.56998339, 0.0002271, 2 ], [ 8819742, 1499993621593, -568.21882918, 0.0002271, 2 ], [ 8819741, 1499993621541, -599.4112884, 0.0002271, 2 ], [ 8819740, 1499993621484, -110.97509029, 0.0002271, 2 ], [ 8819739, 1499993621416, -50, 0.00022492, 2 ], [ 8819738, 1499993621357, -50, 0.00022481, 2 ], [ 8819737, 1499993621272, -602.16479213, 0.00022465, 2 ], [ 8819736, 1499993621192, -5.3639181, 0.00022465, 2 ], [ 8819732, 1499993584813, -50, 0.00022465, 2 ], [ 8819731, 1499993353283, -19, 0.0002659, 2 ], [ 8819729, 1499993352687, -967.61447872, 0.0002659, 2 ], [ 8819727, 1499993352105, -1167.98962257, 0.0002659, 2 ], [ 8819725, 1499993351249, -16023.36348933, 0.0002659, 2 ], [ 8819724, 1499993351230, -2098.64941318, 0.0002659, 2 ], [ 8819719, 1499993347667, -71.1836148, 0.0002659, 2 ], [ 8819718, 1499993347647, -135.7293452, 0.0002658, 2 ], [ 8819717, 1499993347624, -509.22367437, 0.0002658, 2 ], [ 8819712, 1499993346579, -52.37534993, 0.0002658, 2 ], [ 8819708, 1499993343496, -0.65331699, 0.0002658, 2 ], [ 8819707, 1499993343468, -2530.78440774, 0.0002658, 2 ], [ 8819706, 1499993343446, -1263.84, 0.0002658, 2 ], [ 8819705, 1499993343424, -120.35886189, 0.000265, 2 ], [ 8819704, 1499993343403, -120.35886189, 0.000265, 2 ], [ 8819703, 1499993343380, -120.35886189, 0.000265, 2 ], [ 8819702, 1499993343358, -147.42764988, 0.000265, 2 ], [ 8819701, 1499993342997, -1.30474549, 0.000265, 2 ], [ 8819697, 1499993341704, -7127.22537711, 0.000265, 2 ]]"; 18 | 19 | var trades = JsonConvert.DeserializeObject>(json, new TradesResultConverter()); 20 | 21 | Assert.AreEqual(120, trades.Count); 22 | 23 | var trade = trades[0]; 24 | 25 | Assert.AreEqual(8819908, trade.ID); 26 | Assert.AreEqual(1499993669662, trade.MTS); 27 | Assert.AreEqual(-42.48113687, trade.Amount); 28 | Assert.AreEqual(0.00026573, trade.Rate); 29 | Assert.AreEqual(2, trade.Period.Milliseconds); 30 | } 31 | 32 | [TestMethod] 33 | public void TradesDeserializeTest2() 34 | { 35 | //GET: https://api.bitfinex.com/v2/trades/tBTCUSD/hist 36 | string json = "[ [ 43394880,1499994152000,0.17690843,2328.5 ], [ 43394873,1499994150000,0.18519263,2327.4 ], [ 43394867,1499994150000,1.14752541,2327.4 ], [ 43394855,1499994149000,0.05865396,2327.4 ], [ 43394846,1499994147000,0.02318898,2327.4 ], [ 43394836,1499994146000,0.23783591,2327.4 ], [ 43394834,1499994145000,0.02318898,2327.4 ], [ 43394826,1499994144000,0.32221829,2327.4 ], [ 43394819,1499994142000,0.37469225,2327.4 ], [ 43394816,1499994141000,0.03474767,2327.4 ], [ 43394814,1499994141000,0.02318898,2327.4 ], [ 43394810,1499994140000,0.02318898,2327.4 ], [ 43394807,1499994138000,0.02318898,2327.4 ], [ 43394805,1499994138000,0.02318898,2327.4 ], [ 43394774,1499994131000,0.40368858,2328.4 ], [ 43394772,1499994130000,-0.02203571,2325.6 ], [ 43394765,1499994127000,-0.97025747,2325 ], [ 43394764,1499994127000,-0.02974253,2325.1 ], [ 43394761,1499994125000,0.04901382,2328.826517 ], [ 43394749,1499994123000,0.03475254,2328.9 ], [ 43394748,1499994123000,0.38448517,2328.8 ], [ 43394746,1499994123000,0.02317404,2328.8 ], [ 43394736,1499994122000,0.3517295,2328.6 ], [ 43394731,1499994122000,0.0114784,2328.4 ], [ 43394726,1499994121000,0.06794646,2328.6 ], [ 43394725,1499994121000,0.07849665,2328.6 ], [ 43394724,1499994121000,0.08878369,2328.6 ], [ 43394722,1499994121000,0.02318898,2328.6 ], [ 43394720,1499994121000,0.17095246,2328.6 ], [ 43394721,1499994121000,0.41161218,2328.6 ], [ 43394719,1499994121000,1.32474152,2328.48422708 ], [ 43394715,1499994121000,0.79070252,2328.4 ], [ 43394714,1499994121000,0.40200175,2326 ], [ 43394711,1499994120000,-1,2325.8 ], [ 43394712,1499994120000,-1,2324.6 ], [ 43394709,1499994120000,0.02317703,2326 ], [ 43394708,1499994120000,-0.46084585,2326.1 ], [ 43394706,1499994120000,-0.02463224,2327.5 ], [ 43394707,1499994120000,-0.01326427,2327.4 ], [ 43394705,1499994120000,-0.02317802,2327.5 ], [ 43394703,1499994120000,-0.02971186,2327.5 ], [ 43394704,1499994120000,-0.02318898,2327.5 ], [ 43394702,1499994120000,0.06794895,2328.48422708 ], [ 43394698,1499994120000,-0.07849665,2328.5 ], [ 43394696,1499994120000,-0.58516317,2328.5 ], [ 43394694,1499994120000,-2.97594971,2328.5 ], [ 43394693,1499994120000,0.01023869,2328.6 ], [ 43394692,1499994120000,0.04725539,2328.6 ], [ 43394690,1499994120000,1.48713934,2328.6 ], [ 43394689,1499994119000,0.26265666,2328.6 ], [ 43394679,1499994118000,0.58516838,2328.5 ], [ 43394678,1499994118000,2.78,2328.4 ], [ 43394671,1499994117000,0.69470349,2328.5 ], [ 43394659,1499994116000,2.18,2328 ], [ 43394658,1499994116000,2,2328 ], [ 43394657,1499994116000,0.43688155,2327.4 ], [ 43394652,1499994115000,0.25954174,2327.4 ], [ 43394624,1499994114000,0.46085107,2327.3 ], [ 43394619,1499994114000,-1.092,2324.5 ], [ 43394594,1499994111000,0.29256214,2327.4 ], [ 43394593,1499994111000,0.7063306,2327.4 ], [ 43394589,1499994106000,0.27069119,2327.4 ], [ 43394582,1499994106000,1.27858048,2326.3 ], [ 43394585,1499994106000,0.62399278,2327.4 ], [ 43394584,1499994106000,0.09184,2327 ], [ 43394583,1499994106000,0.06101,2327 ], [ 43394576,1499994104000,0.094141,2326.3 ], [ 43394573,1499994104000,0.15572938,2326.3 ], [ 43394570,1499994103000,0.2442483,2326.3 ], [ 43394569,1499994103000,0.02318468,2326.3 ], [ 43394567,1499994102000,0.04332964,2326.3 ], [ 43394565,1499994101000,0.16078652,2326.3 ], [ 43394564,1499994101000,0.09263292,2325.2 ], [ 43394554,1499994100000,0.01450442,2325.2 ], [ 43394552,1499994100000,0.24479336,2325.2 ], [ 43394551,1499994100000,0.03473686,2325.2 ], [ 43394548,1499994100000,1.47532161,2325.2 ], [ 43394545,1499994099000,0.13801083,2325.2 ], [ 43394532,1499994092000,0.0347511,2326.3 ], [ 43394478,1499994077000,-0.07911615,2322.6 ], [ 43394466,1499994072000,0.03472337,2326.7 ], [ 43394436,1499994061000,-0.00255144,2324 ], [ 43394435,1499994061000,-0.05653288,2324.7 ], [ 43394434,1499994061000,-0.02974637,2324.8 ], [ 43394428,1499994059000,-0.19081844,2324.6 ], [ 43394426,1499994058000,-0.03,2324.6 ], [ 43394427,1499994058000,-0.22563985,2324.6 ], [ 43394421,1499994056000,0.02978511,2326.8 ], [ 43394402,1499994053000,0.02975149,2324.1 ], [ 43394401,1499994052000,0.02975149,2324.1 ], [ 43394400,1499994052000,-0.02975405,2324.2 ], [ 43394399,1499994052000,-0.05889999,2324.3 ], [ 43394390,1499994049000,0.24059868,2327 ], [ 43394389,1499994049000,2.15397713,2326.7 ], [ 43394373,1499994042000,0.2649,2326.9 ], [ 43394371,1499994041000,0.29952499,2326.8 ], [ 43394370,1499994041000,0.231,2326.7 ], [ 43394369,1499994041000,0.22570366,2326.5 ], [ 43394358,1499994038000,0.16658644,2326.8 ], [ 43394357,1499994038000,0.19205067,2326.3 ], [ 43394356,1499994037000,0.03103501,2326.3 ], [ 43394350,1499994037000,0.09209846,2326.3 ], [ 43394346,1499994036000,0.30647881,2326.3 ], [ 43394338,1499994035000,0.65932398,2326.3 ], [ 43394320,1499994026000,0.20895066,2326.1 ], [ 43394321,1499994026000,0.46331131,2326.5 ], [ 43394316,1499994023000,0.23867355,2326.1 ], [ 43394315,1499994023000,0.9607694,2326.1 ], [ 43394309,1499994022000,0.15718346,2326.1 ], [ 43394295,1499994016000,0.03842293,2326.1 ], [ 43394290,1499994014000,1.0187638,2326.2 ], [ 43394233,1499994008000,0.23819137,2326.4 ], [ 43394231,1499994008000,0.01613,2324.9 ], [ 43394232,1499994008000,0.18408,2324.9 ], [ 43394230,1499994007000,0.07501416,2324.8 ], [ 43394229,1499994007000,0.95048185,2324.7 ], [ 43394212,1499993988000,-0.04514027,2322.5 ], [ 43394210,1499993987000,0.01,2324.7 ], [ 43394206,1499993987000,-0.03370366,2322.4 ], [ 43394200,1499993987000,0.01001815,2324.7 ] ]"; 37 | 38 | var trades = JsonConvert.DeserializeObject>(json, new TradesResultConverter()); 39 | 40 | Assert.AreEqual(120, trades.Count); 41 | 42 | var trade = trades[0]; 43 | 44 | Assert.AreEqual(43394880, trade.ID); 45 | Assert.AreEqual(1499994152000, trade.MTS); 46 | Assert.AreEqual(0.17690843, trade.Amount); 47 | Assert.AreEqual(2328.5, trade.Price); 48 | } 49 | 50 | [TestMethod] 51 | public void TradesClientTest() 52 | { 53 | var client = new BitfinexRestClient(); 54 | var trades = client.GetTrades("tBTCUSD", 50, 0, 0, SortDirection.NewestToOldest); 55 | 56 | Assert.AreEqual(50, trades.Count); 57 | } 58 | 59 | [TestMethod] 60 | public void TradesClientTest2() 61 | { 62 | var client = new BitfinexRestClient(); 63 | var trades = client.GetTrades("tBTCUSD", 120, 1501105149000, 1501115149000, SortDirection.NewestToOldest); 64 | 65 | Assert.AreEqual(120, trades.Count); 66 | } 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Bitfinex/IBitfinexRestClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using Bitfinex.Models; 5 | 6 | namespace Bitfinex 7 | { 8 | public interface IBitfinexRestClient 9 | { 10 | /// 11 | /// Get charting candle info 12 | /// 13 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 14 | /// The symbol you want information about. 15 | /// Available values: "last", "hist" 16 | /// A list of candle information 17 | List GetCandles(TimeFrame timeframe, Symbol symbol, Section section); 18 | 19 | /// 20 | /// Get charting candle info 21 | /// 22 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 23 | /// The symbol you want information about. 24 | /// Available values: "last", "hist" 25 | /// Number of candles requested 26 | /// A list of candle information 27 | List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit); 28 | 29 | /// 30 | /// Get charting candle info 31 | /// 32 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 33 | /// The symbol you want information about. 34 | /// Available values: "last", "hist" 35 | /// Number of candles requested 36 | /// Filter start (ms) 37 | /// A list of candle information 38 | List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start); 39 | 40 | /// 41 | /// Get charting candle info 42 | /// 43 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 44 | /// The symbol you want information about. 45 | /// Available values: "last", "hist" 46 | /// Number of candles requested 47 | /// Filter start (ms) 48 | /// Filter end (ms) 49 | /// A list of candle information 50 | List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end); 51 | 52 | /// 53 | /// Get charting candle info 54 | /// 55 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 56 | /// The symbol you want information about. 57 | /// Available values: "last", "hist" 58 | /// Number of candles requested 59 | /// Filter start (ms) 60 | /// Filter end (ms) 61 | /// Default new > old 62 | /// A list of candle information 63 | List GetCandles(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end, SortDirection sortDirection); 64 | 65 | /// 66 | /// Get charting candle info 67 | /// 68 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 69 | /// The symbol you want information about. 70 | /// Available values: "last", "hist" 71 | /// A list of candle information 72 | Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section); 73 | 74 | /// 75 | /// Get charting candle info 76 | /// 77 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 78 | /// The symbol you want information about. 79 | /// Available values: "last", "hist" 80 | /// Number of candles requested 81 | /// A list of candle information 82 | Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit); 83 | 84 | /// 85 | /// Get charting candle info 86 | /// 87 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 88 | /// The symbol you want information about. 89 | /// Available values: "last", "hist" 90 | /// Number of candles requested 91 | /// Filter start (ms) 92 | /// A list of candle information 93 | Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start); 94 | 95 | /// 96 | /// Get charting candle info 97 | /// 98 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 99 | /// The symbol you want information about. 100 | /// Available values: "last", "hist" 101 | /// Number of candles requested 102 | /// Filter start (ms) 103 | /// Filter end (ms) 104 | /// A list of candle information 105 | Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end); 106 | 107 | /// 108 | /// Get charting candle info 109 | /// 110 | /// Available values: '1m', '5m', '15m', '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M' 111 | /// The symbol you want information about. 112 | /// Available values: "last", "hist" 113 | /// Number of candles requested 114 | /// Filter start (ms) 115 | /// Filter end (ms) 116 | /// Default new > old 117 | /// A list of candle information 118 | Task> GetCandlesAsync(TimeFrame timeframe, Symbol symbol, Section section, int limit, long start, long end, SortDirection sortDirection); 119 | 120 | /// 121 | /// Get pertinent details of trades, such as price, size and time. 122 | /// 123 | /// The symbol you want information about. 124 | /// List of trades 125 | List GetTrades(string symbol); 126 | 127 | /// 128 | /// Get pertinent details of trades, such as price, size and time. 129 | /// 130 | /// The symbol you want information about. 131 | /// Number of records 132 | /// List of trades 133 | List GetTrades(string symbol, int limit); 134 | 135 | /// 136 | /// Get pertinent details of trades, such as price, size and time. 137 | /// 138 | /// The symbol you want information about. 139 | /// Number of records 140 | /// Millisecond start time 141 | /// List of trades 142 | List GetTrades(string symbol, int limit, long start); 143 | 144 | /// 145 | /// Get pertinent details of trades, such as price, size and time. 146 | /// 147 | /// The symbol you want information about. 148 | /// Number of records 149 | /// Millisecond start time 150 | /// Millisecond end time 151 | /// List of trades 152 | List GetTrades(string symbol, int limit, long start, long end); 153 | 154 | /// 155 | /// Get pertinent details of trades, such as price, size and time. 156 | /// 157 | /// The symbol you want information about. 158 | /// Number of records 159 | /// Millisecond start time 160 | /// Millisecond end time 161 | /// 162 | /// List of trades 163 | List GetTrades(string symbol, int limit, long start, long end, SortDirection sortDirection); 164 | 165 | /// 166 | /// Get pertinent details of trades, such as price, size and time. 167 | /// 168 | /// The symbol you want information about. 169 | /// List of trades 170 | Task> GetTradesAsync(string symbol); 171 | 172 | /// 173 | /// Get pertinent details of trades, such as price, size and time. 174 | /// 175 | /// The symbol you want information about. 176 | /// Number of records (default 120) 177 | /// List of trades 178 | Task> GetTradesAsync(string symbol, int limit); 179 | 180 | /// 181 | /// Get pertinent details of trades, such as price, size and time. 182 | /// 183 | /// The symbol you want information about. 184 | /// Number of records (default 120) 185 | /// Millisecond start time (default 0) 186 | /// List of trades 187 | Task> GetTradesAsync(string symbol, int limit, long start); 188 | 189 | /// 190 | /// Get pertinent details of trades, such as price, size and time. 191 | /// 192 | /// The symbol you want information about. 193 | /// Number of records (default 120) 194 | /// Millisecond start time (default 0) 195 | /// Millisecond end time (default 0) 196 | /// List of trades 197 | Task> GetTradesAsync(string symbol, int limit, long start, long end); 198 | 199 | /// 200 | /// Get pertinent details of trades, such as price, size and time. 201 | /// 202 | /// The symbol you want information about. 203 | /// Number of records (default 120) 204 | /// Millisecond start time (default 0) 205 | /// Millisecond end time (default 0) 206 | /// Default new > old 207 | /// List of trades 208 | Task> GetTradesAsync(string symbol, int limit, long start, long end, SortDirection sortDirection); 209 | 210 | string BaseUrl { get; set; } 211 | CancellationToken CancellationToken { get; set; } 212 | 213 | /// 214 | /// Get a high-level overview of the specified symbol. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 215 | /// 216 | /// A symbol (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 217 | /// Ticker 218 | ITicker GetTicker(string symbol); 219 | 220 | /// 221 | /// Get a high-level overview of the specified symbols. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 222 | /// 223 | /// A list of symbols (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 224 | /// List of tickers 225 | List GetTickers(string[] symbols); 226 | 227 | /// 228 | /// Get a high-level overview of the specified symbol. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 229 | /// 230 | /// A symbol (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 231 | /// Ticker 232 | Task GetTickerAsync(string symbol); 233 | 234 | /// 235 | /// Get a high-level overview of the specified symbols. It shows you the current best bid and ask, as well as the last trade price. It also includes information such as daily volume and how much the price has moved over the last day. 236 | /// 237 | /// A list of symbols (eg BTCUSD) prefixed with either t (for Trading) or f (for Funding). eg tBTCUSD 238 | /// List of tickers 239 | Task> GetTickersAsync(string[] symbols); 240 | 241 | /// 242 | /// Get statistics about the requested pair. 243 | /// 244 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 245 | /// The symbol you want information about. 246 | /// Available values: "long", "short" 247 | /// Available values: "last", "hist" 248 | /// List of MTS and Value stats for the requested pair 249 | List GetStats(Key key, Symbol symbol, Side side, Section section); 250 | 251 | /// 252 | /// Get statistics about the requested pair. 253 | /// 254 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 255 | /// The symbol you want information about. 256 | /// Available values: "long", "short" 257 | /// Available values: "last", "hist" 258 | /// Default new > old 259 | /// List of MTS and Value stats for the requested pair 260 | List GetStats(Key key, Symbol symbol, Side side, Section section, SortDirection sortDirection); 261 | 262 | /// 263 | /// Get statistics about the requested pair. 264 | /// 265 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 266 | /// The symbol you want information about. 267 | /// Available values: "long", "short" 268 | /// Available values: "last", "hist" 269 | /// List of MTS and Value stats for the requested pair 270 | Task> GetStatsAsync(Key key, Symbol symbol, Side side, Section section); 271 | 272 | /// 273 | /// Get statistics about the requested pair. 274 | /// 275 | /// Allowed values: "funding.size", "credits.size", "credits.size.sym", "pos.size" 276 | /// The symbol you want information about. 277 | /// Available values: "long", "short" 278 | /// Available values: "last", "hist" 279 | /// Default new > old 280 | /// List of MTS and Value stats for the requested pair 281 | Task> GetStatsAsync(Key key, Symbol symbol, Side side, Section section, SortDirection sortDirection); 282 | 283 | /// 284 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 285 | /// 286 | /// The symbol you want information about. 287 | /// Level of price aggregation (P0, P1, P2, P3, R0) 288 | /// List of books 289 | List GetBooks(string symbol, Precision precision); 290 | 291 | /// 292 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 293 | /// 294 | /// The symbol you want information about. 295 | /// Level of price aggregation (P0, P1, P2, P3, R0) 296 | /// Number of price points 297 | /// List of books 298 | List GetBooks(string symbol, Precision precision, int len); 299 | 300 | /// 301 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 302 | /// 303 | /// The symbol you want information about. 304 | /// Level of price aggregation (P0, P1, P2, P3, R0) 305 | /// List of books 306 | Task> GetBooksAsync(string symbol, Precision precision); 307 | 308 | /// 309 | /// Retrieve state of the Bitfinex order book. It is provided on a price aggregated basis, with customizable precision. 310 | /// 311 | /// The symbol you want information about. 312 | /// Level of price aggregation (P0, P1, P2, P3, R0) 313 | /// Number of price points 314 | /// List of books 315 | Task> GetBooksAsync(string symbol, Precision precision, int len); 316 | } 317 | } --------------------------------------------------------------------------------