@@ -10,11 +10,12 @@ The above copyright notice and this permission notice shall be included in all c
10
10
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11
11
*/
12
12
13
- using ExchangeSharp . OKGroup ;
14
- using Newtonsoft . Json . Linq ;
15
13
using System ;
16
14
using System . Collections . Generic ;
15
+ using System . Linq ;
17
16
using System . Threading . Tasks ;
17
+ using ExchangeSharp . OKGroup ;
18
+ using Newtonsoft . Json . Linq ;
18
19
19
20
namespace ExchangeSharp
20
21
{
@@ -27,6 +28,11 @@ public sealed partial class ExchangeOKExAPI : OKGroupCommon
27
28
public string BaseUrlV5 { get ; set ; } = "https://okex.com/api/v5" ;
28
29
protected override bool IsFuturesAndSwapEnabled { get ; } = true ;
29
30
31
+ public override string PeriodSecondsToString ( int seconds )
32
+ {
33
+ return CryptoUtility . SecondsToPeriodString ( seconds , true ) ;
34
+ }
35
+
30
36
protected internal override async Task < IEnumerable < ExchangeMarket > > OnGetMarketSymbolsMetadataAsync ( )
31
37
{
32
38
/*
@@ -61,61 +67,54 @@ protected internal override async Task<IEnumerable<ExchangeMarket>> OnGetMarketS
61
67
]
62
68
}
63
69
*/
64
- List < ExchangeMarket > markets = new List < ExchangeMarket > ( ) ;
70
+ var markets = new List < ExchangeMarket > ( ) ;
65
71
parseMarketSymbolTokens ( await MakeJsonRequestAsync < JToken > (
66
72
"/public/instruments?instType=SPOT" , BaseUrlV5 ) ) ;
67
- if ( IsFuturesAndSwapEnabled )
68
- {
69
- parseMarketSymbolTokens ( await MakeJsonRequestAsync < JToken > (
70
- "/public/instruments?instType=FUTURES" , BaseUrlV5 ) ) ;
71
- parseMarketSymbolTokens ( await MakeJsonRequestAsync < JToken > (
72
- "/public/instruments?instType=SWAP" , BaseUrlV5 ) ) ;
73
- }
73
+ if ( ! IsFuturesAndSwapEnabled )
74
+ return markets ;
75
+ parseMarketSymbolTokens ( await MakeJsonRequestAsync < JToken > (
76
+ "/public/instruments?instType=FUTURES" , BaseUrlV5 ) ) ;
77
+ parseMarketSymbolTokens ( await MakeJsonRequestAsync < JToken > (
78
+ "/public/instruments?instType=SWAP" , BaseUrlV5 ) ) ;
79
+ return markets ;
80
+
74
81
void parseMarketSymbolTokens ( JToken allMarketSymbolTokens )
75
82
{
76
- foreach ( JToken marketSymbolToken in allMarketSymbolTokens )
77
- {
78
- var isSpot = marketSymbolToken [ "instType" ] . Value < string > ( ) == "SPOT" ;
79
- var baseCurrency = isSpot
80
- ? marketSymbolToken [ "baseCcy" ] . Value < string > ( )
81
- : marketSymbolToken [ "settleCcy" ] . Value < string > ( ) ;
82
- var quoteCurrency = isSpot
83
- ? marketSymbolToken [ "quoteCcy" ] . Value < string > ( )
84
- : marketSymbolToken [ "ctValCcy" ] . Value < string > ( ) ;
85
- var market = new ExchangeMarket
86
- {
87
- MarketSymbol = marketSymbolToken [ "instId" ] . Value < string > ( ) ,
88
- IsActive = marketSymbolToken [ "state" ] . Value < string > ( ) == "live" ,
89
- QuoteCurrency = quoteCurrency ,
90
- BaseCurrency = baseCurrency ,
91
- PriceStepSize = marketSymbolToken [ "tickSz" ] . ConvertInvariant < decimal > ( ) ,
92
- MinPrice = marketSymbolToken [ "tickSz" ] . ConvertInvariant < decimal > ( ) , // assuming that this is also the min price since it isn't provided explicitly by the exchange
93
- MinTradeSize = marketSymbolToken [ "minSz" ] . ConvertInvariant < decimal > ( ) ,
94
- QuantityStepSize = marketSymbolToken [ "lotSz" ] . ConvertInvariant < decimal > ( ) ,
95
- } ;
96
- markets . Add ( market ) ;
97
- }
83
+ markets . AddRange ( from marketSymbolToken in allMarketSymbolTokens
84
+ let isSpot = marketSymbolToken [ "instType" ] . Value < string > ( ) == "SPOT"
85
+ let baseCurrency = isSpot ? marketSymbolToken [ "baseCcy" ] . Value < string > ( ) : marketSymbolToken [ "settleCcy" ] . Value < string > ( )
86
+ let quoteCurrency = isSpot ? marketSymbolToken [ "quoteCcy" ] . Value < string > ( ) : marketSymbolToken [ "ctValCcy" ] . Value < string > ( )
87
+ select new ExchangeMarket
88
+ {
89
+ MarketSymbol = marketSymbolToken [ "instId" ] . Value < string > ( ) ,
90
+ IsActive = marketSymbolToken [ "state" ] . Value < string > ( ) == "live" ,
91
+ QuoteCurrency = quoteCurrency ,
92
+ BaseCurrency = baseCurrency ,
93
+ PriceStepSize = marketSymbolToken [ "tickSz" ] . ConvertInvariant < decimal > ( ) ,
94
+ MinPrice = marketSymbolToken [ "tickSz" ] . ConvertInvariant < decimal > ( ) , // assuming that this is also the min price since it isn't provided explicitly by the exchange
95
+ MinTradeSize = marketSymbolToken [ "minSz" ] . ConvertInvariant < decimal > ( ) ,
96
+ QuantityStepSize = marketSymbolToken [ "lotSz" ] . ConvertInvariant < decimal > ( )
97
+ } ) ;
98
98
}
99
-
100
- return markets ;
101
99
}
102
100
103
101
protected override async Task < ExchangeTicker > OnGetTickerAsync ( string marketSymbol )
104
102
{
105
103
var tickerResponse = await MakeJsonRequestAsync < JToken > ( $ "/market/ticker?instId={ marketSymbol } ", BaseUrlV5 ) ;
106
- var symbol = tickerResponse [ "instId" ] . Value < string > ( ) ;
107
- return await ParseTickerV5Async ( tickerResponse , symbol ) ;
104
+ var symbol = tickerResponse [ 0 ] [ "instId" ] . Value < string > ( ) ;
105
+ return await ParseTickerV5Async ( tickerResponse [ 0 ] , symbol ) ;
108
106
}
109
107
110
108
protected override async Task < IEnumerable < KeyValuePair < string , ExchangeTicker > > > OnGetTickersAsync ( )
111
109
{
112
- List < KeyValuePair < string , ExchangeTicker > > tickers = new List < KeyValuePair < string , ExchangeTicker > > ( ) ;
110
+ var tickers = new List < KeyValuePair < string , ExchangeTicker > > ( ) ;
113
111
await parseData ( await MakeJsonRequestAsync < JToken > ( "/market/tickers?instType=SPOT" , BaseUrlV5 ) ) ;
114
- if ( IsFuturesAndSwapEnabled )
115
- {
116
- await parseData ( await MakeJsonRequestAsync < JToken > ( "/market/tickers?instType=FUTURES" , BaseUrlV5 ) ) ;
117
- await parseData ( await MakeJsonRequestAsync < JToken > ( "/market/tickers?instType=SWAP" , BaseUrlV5 ) ) ;
118
- }
112
+ if ( ! IsFuturesAndSwapEnabled )
113
+ return tickers ;
114
+ await parseData ( await MakeJsonRequestAsync < JToken > ( "/market/tickers?instType=FUTURES" , BaseUrlV5 ) ) ;
115
+ await parseData ( await MakeJsonRequestAsync < JToken > ( "/market/tickers?instType=SWAP" , BaseUrlV5 ) ) ;
116
+ return tickers ;
117
+
119
118
async Task parseData ( JToken tickerResponse )
120
119
{
121
120
/*{
@@ -148,49 +147,83 @@ async Task parseData(JToken tickerResponse)
148
147
foreach ( JToken t in tickerResponse )
149
148
{
150
149
var symbol = t [ "instId" ] . Value < string > ( ) ;
151
- ExchangeTicker ticker = await ParseTickerV5Async ( t , symbol ) ;
150
+ var ticker = await ParseTickerV5Async ( t , symbol ) ;
152
151
tickers . Add ( new KeyValuePair < string , ExchangeTicker > ( symbol , ticker ) ) ;
153
152
}
154
153
}
155
-
156
- return tickers ;
157
154
}
158
155
159
- protected override async Task < IEnumerable < ExchangeTrade > > OnGetRecentTradesAsync ( string marketSymbol , int ? limit )
156
+ protected override async Task < IEnumerable < ExchangeTrade > > OnGetRecentTradesAsync ( string marketSymbol ,
157
+ int ? limit = null )
160
158
{
161
- limit = limit ?? 500 ;
159
+ limit ??= 500 ;
162
160
marketSymbol = NormalizeMarketSymbol ( marketSymbol ) ;
163
- List < ExchangeTrade > trades = new List < ExchangeTrade > ( ) ;
164
- var recentTradesResponse = await MakeJsonRequestAsync < JToken > ( $ "/market/trades?instId={ marketSymbol } &limit={ limit } ", BaseUrlV5 ) ;
165
- foreach ( var t in recentTradesResponse )
166
- {
167
- trades . Add (
168
- t . ParseTrade (
169
- amountKey : "sz" ,
170
- priceKey : "px" ,
171
- typeKey : "side" ,
172
- timestampKey : "ts" ,
173
- timestampType : TimestampType . UnixMilliseconds ,
174
- idKey : "tradeId" ) ) ;
161
+ var recentTradesResponse =
162
+ await MakeJsonRequestAsync < JToken > ( $ "/market/trades?instId={ marketSymbol } &limit={ limit } ", BaseUrlV5 ) ;
163
+ return recentTradesResponse . Select ( t => t . ParseTrade (
164
+ "sz" , "px" , "side" , "ts" , TimestampType . UnixMilliseconds , "tradeId" ) )
165
+ . ToList ( ) ;
166
+ }
167
+
168
+ protected override async Task < ExchangeOrderBook > OnGetOrderBookAsync ( string marketSymbol , int maxCount = 100 )
169
+ {
170
+ var token = await MakeJsonRequestAsync < JToken > ( $ "/market/books?instId={ marketSymbol } &sz={ maxCount } ", BaseUrlV5 ) ;
171
+ return token [ 0 ] . ParseOrderBookFromJTokenArrays ( maxCount : maxCount ) ;
172
+ }
173
+
174
+ protected override async Task < IEnumerable < MarketCandle > > OnGetCandlesAsync ( string marketSymbol , int periodSeconds , DateTime ? startDate = null , DateTime ? endDate = null , int ? limit = null )
175
+ {
176
+ /*
177
+ {
178
+ "code":"0",
179
+ "msg":"",
180
+ "data":[
181
+ [
182
+ "1597026383085", timestamp
183
+ "3.721", open
184
+ "3.743", high
185
+ "3.677", low
186
+ "3.708", close
187
+ "8422410", volume
188
+ "22698348.04828491" volCcy (Quote)
189
+ ],..
190
+ ]
175
191
}
192
+ */
176
193
177
- return trades ;
194
+ var candles = new List < MarketCandle > ( ) ;
195
+ var url = $ "/market/history-candles?instId={ marketSymbol } ";
196
+ if ( startDate . HasValue )
197
+ url += "&after=" + ( long ) startDate . Value . UnixTimestampFromDateTimeMilliseconds ( ) ;
198
+ if ( endDate . HasValue )
199
+ url += "&before=" + ( long ) endDate . Value . UnixTimestampFromDateTimeMilliseconds ( ) ;
200
+ if ( limit . HasValue )
201
+ url += "&limit=" + limit . Value . ToStringInvariant ( ) ;
202
+ var periodString = PeriodSecondsToString ( periodSeconds ) ;
203
+ url += $ "&bar={ periodString } ";
204
+ var obj = await MakeJsonRequestAsync < JToken > ( url , BaseUrlV5 ) ;
205
+ foreach ( JArray token in obj )
206
+ candles . Add ( this . ParseCandle ( token , marketSymbol , periodSeconds , 1 , 2 , 3 , 4 , 0 , TimestampType . UnixMilliseconds , 5 , 6 ) ) ;
207
+ return candles ;
178
208
}
179
209
180
210
private async Task < ExchangeTicker > ParseTickerV5Async ( JToken t , string symbol )
181
211
{
182
212
return await this . ParseTickerAsync (
183
- t ,
184
- symbol ,
185
- askKey : "askPx" ,
186
- bidKey : "bidPx" ,
187
- lastKey : "last" ,
188
- baseVolumeKey : "vol24h" ,
189
- quoteVolumeKey : "volCcy24h" ,
190
- timestampKey : "ts" ,
191
- timestampType : TimestampType . UnixMilliseconds ) ;
213
+ token : t ,
214
+ marketSymbol : symbol ,
215
+ askKey : "askPx" ,
216
+ bidKey : "bidPx" ,
217
+ lastKey : "last" ,
218
+ baseVolumeKey : "vol24h" ,
219
+ quoteVolumeKey : "volCcy24h" ,
220
+ timestampKey : "ts" ,
221
+ timestampType : TimestampType . UnixMilliseconds ) ;
192
222
}
193
223
}
194
224
195
- public partial class ExchangeName { public const string OKEx = "OKEx" ; }
225
+ public partial class ExchangeName
226
+ {
227
+ public const string OKEx = "OKEx" ;
228
+ }
196
229
}
0 commit comments