-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Dmitrii Doronin <[email protected]> Co-authored-by: Stas Gryumov <[email protected]>
- Loading branch information
1 parent
d996638
commit 1905c14
Showing
14 changed files
with
585 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Cryptocom | ||
|
||
```@docs | ||
CryptoAPIs.Cryptocom.CryptocomClient | ||
CryptoAPIs.Cryptocom.CryptocomAPIError | ||
CryptoAPIs.Cryptocom.Data | ||
``` | ||
|
||
## Spot | ||
|
||
```@docs | ||
CryptoAPIs.Cryptocom.Spot.public_client | ||
``` | ||
|
||
```@docs | ||
CryptoAPIs.Cryptocom.Spot.candle | ||
CryptoAPIs.Cryptocom.Spot.get_instruments | ||
CryptoAPIs.Cryptocom.Spot.ticker | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Cryptocom/Spot | ||
# https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#introduction | ||
|
||
using Dates | ||
using CryptoAPIs | ||
using CryptoAPIs.Cryptocom | ||
|
||
CryptoAPIs.Cryptocom.Spot.candle(; | ||
instrument_name = "BTC_USDT", | ||
timeframe = Cryptocom.Spot.Candle.M1, | ||
start_ts = Dates.now() - Dates.Day(1), | ||
end_ts = Dates.now(), | ||
) | ||
|
||
CryptoAPIs.Cryptocom.Spot.get_instruments() | ||
|
||
CryptoAPIs.Cryptocom.Spot.ticker(; instrument_name = "BTCUSD-PERP") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
module Cryptocom | ||
|
||
export CryptocomCommonQuery, | ||
CryptocomPublicQuery, | ||
CryptocomAccessQuery, | ||
CryptocomPrivateQuery, | ||
CryptocomAPIError, | ||
CryptocomClient, | ||
CryptocomData | ||
|
||
using Serde | ||
using Dates, NanoDates, Base64, Nettle | ||
|
||
using ..CryptoAPIs | ||
using ..CryptoAPIs: Maybe, AbstractAPIsError, AbstractAPIsData, AbstractAPIsQuery, AbstractAPIsClient | ||
|
||
abstract type CryptocomData <: AbstractAPIsData end | ||
abstract type CryptocomCommonQuery <: AbstractAPIsQuery end | ||
abstract type CryptocomPublicQuery <: CryptocomCommonQuery end | ||
abstract type CryptocomAccessQuery <: CryptocomCommonQuery end | ||
abstract type CryptocomPrivateQuery <: CryptocomCommonQuery end | ||
|
||
""" | ||
Data{D} <: AbstractAPIsData | ||
## Required fields | ||
- `id::Int64`: Return id. | ||
- `method::String`: Return method endpoint. | ||
- `code::String`: Return code. | ||
- `result::D`: Request result data. | ||
""" | ||
struct Data{D<:AbstractAPIsData} <: AbstractAPIsData | ||
id::Int64 | ||
method::String | ||
code::String | ||
result::D | ||
end | ||
|
||
""" | ||
CryptocomClient <: AbstractAPIsClient | ||
Client info. | ||
## Required fields | ||
- `base_url::String`: Base URL for the client. | ||
## Optional fields | ||
- `public_key::String`: Public key for authentication. | ||
- `secret_key::String`: Secret key for authentication. | ||
- `interface::String`: Interface for the client. | ||
- `proxy::String`: Proxy information for the client. | ||
- `account_name::String`: Account name associated with the client. | ||
- `description::String`: Description of the client. | ||
""" | ||
Base.@kwdef struct CryptocomClient <: AbstractAPIsClient | ||
base_url::String | ||
public_key::Maybe{String} = nothing | ||
secret_key::Maybe{String} = nothing | ||
interface::Maybe{String} = nothing | ||
proxy::Maybe{String} = nothing | ||
account_name::Maybe{String} = nothing | ||
description::Maybe{String} = nothing | ||
end | ||
|
||
""" | ||
CryptocomAPIError{T} <: AbstractAPIsError | ||
Exception thrown when an API method fails with code `T`. | ||
## Required fields | ||
- `code::Int64`: Error code. | ||
## Optional fields | ||
- `message::String`: Error message. | ||
- `description::String`: Error description. | ||
""" | ||
struct CryptocomAPIError{T} <: AbstractAPIsError | ||
code::Int64 | ||
message::Maybe{String} | ||
description::Maybe{String} | ||
|
||
function CryptocomAPIError(code::Int64, x...) | ||
return new{code}(code, x...) | ||
end | ||
end | ||
|
||
CryptoAPIs.error_type(::CryptocomClient) = CryptocomAPIError | ||
|
||
function Base.show(io::IO, e::CryptocomAPIError) | ||
return print(io, "code = ", "\"", e.code, "\"", ", ", "msg = ", "\"", e.message, "\"", ", ", "desc = ", "\"", e.description, "\"") | ||
end | ||
|
||
struct CryptocomUndefError <: AbstractAPIsError | ||
e::Exception | ||
msg::String | ||
end | ||
|
||
function CryptoAPIs.request_sign!(::CryptocomClient, query::Q, ::String)::Q where {Q<:CryptocomPublicQuery} | ||
return query | ||
end | ||
|
||
function CryptoAPIs.request_body(::Q)::String where {Q<:CryptocomCommonQuery} | ||
return "" | ||
end | ||
|
||
function CryptoAPIs.request_query(query::Q)::String where {Q<:CryptocomCommonQuery} | ||
return Serde.to_query(query) | ||
end | ||
|
||
function CryptoAPIs.request_headers(client::CryptocomClient, ::CryptocomPublicQuery)::Vector{Pair{String,String}} | ||
return Pair{String,String}[ | ||
"Content-Type" => "application/json" | ||
] | ||
end | ||
|
||
include("Utils.jl") | ||
|
||
include("Spot/Spot.jl") | ||
using .Spot | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Cryptocom/Errors | ||
# https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#response-and-reason-codes | ||
|
||
import ..CryptoAPIs: APIsResult, APIsUndefError, isretriable, retry_maxcount, retry_timeout | ||
|
||
# UNDEF | ||
isretriable(::APIsResult{CryptocomAPIError}) = true | ||
|
||
# Success | ||
isretriable(e::APIsResult{CryptocomAPIError{0}}) = false | ||
|
||
# Server Timeout | ||
isretriable(e::APIsResult{CryptocomAPIError{40801}}) = true | ||
retry_timeout(e::APIsResult{CryptocomAPIError{40801}}) = 10 | ||
retry_maxcount(e::APIsResult{CryptocomAPIError{40801}}) = 50 | ||
|
||
# Requests have exceeded rate limits | ||
isretriable(e::APIsResult{CryptocomAPIError{42901}}) = true | ||
retry_timeout(e::APIsResult{CryptocomAPIError{42901}}) = 10 | ||
retry_maxcount(e::APIsResult{CryptocomAPIError{42901}}) = 50 | ||
|
||
#Instrument has expired | ||
isretriable(e::APIsResult{CryptocomAPIError{206}}) = false | ||
|
||
#Instrument is not tradable | ||
isretriable(e::APIsResult{CryptocomAPIError{208}}) = false | ||
|
||
#Market is not open | ||
isretriable(e::APIsResult{CryptocomAPIError{309}}) = false | ||
|
||
#Bad request | ||
isretriable(e::APIsResult{CryptocomAPIError{40001}}) = false | ||
|
||
#Required argument is blank or missing | ||
isretriable(e::APIsResult{CryptocomAPIError{40004}}) = false | ||
|
||
#Invalid date | ||
isretriable(e::APIsResult{CryptocomAPIError{40005}}) = false | ||
|
||
#IP address not whitelisted | ||
isretriable(e::APIsResult{CryptocomAPIError{40103}}) = false | ||
|
||
#Not found | ||
isretriable(e::APIsResult{CryptocomAPIError{40401}}) = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
module Candle | ||
|
||
export CandleQuery, | ||
CandleData, | ||
candle | ||
|
||
using Serde | ||
using Dates, NanoDates, TimeZones | ||
|
||
using CryptoAPIs.Cryptocom | ||
using CryptoAPIs.Cryptocom: Data | ||
using CryptoAPIs: Maybe, APIsRequest | ||
|
||
@enum TimeInterval m1 m5 m15 m30 h1 h2 h4 h12 d1 d7 d14 M1 | ||
|
||
Base.@kwdef struct CandleQuery <: CryptocomPublicQuery | ||
instrument_name::String | ||
timeframe::Maybe{TimeInterval} = nothing | ||
count::Maybe{Int64} = nothing | ||
start_ts::Maybe{DateTime} = nothing | ||
end_ts::Maybe{DateTime} = nothing | ||
end | ||
|
||
function Serde.ser_type(::Type{<:CandleQuery}, x::TimeInterval)::String | ||
x == m1 && return "1m" | ||
x == m5 && return "5m" | ||
x == m15 && return "15m" | ||
x == m30 && return "30m" | ||
x == h1 && return "1h" | ||
x == h2 && return "2h" | ||
x == h4 && return "4h" | ||
x == h12 && return "12h" | ||
x == d1 && return "1D" | ||
x == d7 && return "7D" | ||
x == d14 && return "14D" | ||
x == M1 && return "1M" | ||
end | ||
|
||
struct CandleInfo <: CryptocomData | ||
o::Maybe{Float64} | ||
h::Maybe{Float64} | ||
l::Maybe{Float64} | ||
c::Maybe{Float64} | ||
v::Maybe{Float64} | ||
t::NanoDate | ||
end | ||
|
||
function Serde.isempty(::Type{CandleInfo}, x)::Bool | ||
return x === "" | ||
end | ||
|
||
struct CandleData <: CryptocomData | ||
interval::String | ||
data::Vector{CandleInfo} | ||
instrument_name::String | ||
end | ||
|
||
function Serde.isempty(::Type{CandleData}, x)::Bool | ||
return x == [] | ||
end | ||
|
||
""" | ||
candle(client::CryptocomClient, query::CandleQuery) | ||
candle(client::CryptocomClient = Cryptocom.Spot.public_client; kw...) | ||
Retrieves candlesticks (k-line data history) over a given period for an instrument. | ||
[`GET public/get-candlestick`](https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-candlestick) | ||
## Parameters: | ||
| Parameter | Type | Required | Description | | ||
|:----------------|:-------------|:---------|:----------------------------------------| | ||
| instrument_name | String | true | | | ||
| timeframe | TimeInterval | false | m1 m5 m15 m30 h1 h2 h4 h12 d1 d7 d14 M1 | | ||
| count | Int64 | false | | | ||
| start_ts | Int64 | false | | | ||
| end_ts | Int64 | false | | | ||
## Code samples: | ||
```julia | ||
using Serde | ||
using CryptoAPIs.Cryptocom | ||
result = Cryptocom.Spot.candle(; | ||
instrument_name = "BTC_USDT", | ||
timeframe = Cryptocom.Spot.Candle.M1, | ||
) | ||
to_pretty_json(result.result) | ||
``` | ||
## Result: | ||
```json | ||
{ | ||
"id":-1, | ||
"method":"public/get-candlestick", | ||
"code":"0", | ||
"result":{ | ||
"interval":"1M", | ||
"data":[ | ||
{ | ||
"o":19000.0, | ||
"h":22982.05, | ||
"l":15492.33, | ||
"c":17170.28, | ||
"v":150666.07457, | ||
"t":"2022-11-01T00:00:00" | ||
}, | ||
{ | ||
"o":17166.5, | ||
"h":18372.46, | ||
"l":16263.22, | ||
"c":16539.69, | ||
"v":51215.88412, | ||
"t":"2022-12-01T00:00:00" | ||
... | ||
], | ||
"instrument_name":"BTC_USDT" | ||
} | ||
} | ||
``` | ||
""" | ||
function candle(client::CryptocomClient, query::CandleQuery) | ||
return APIsRequest{Data{CandleData}}("GET", "public/get-candlestick", query)(client) | ||
end | ||
|
||
function candle(client::CryptocomClient = Cryptocom.Spot.public_client; kw...) | ||
return candle(client, CandleQuery(; kw...)) | ||
end | ||
|
||
end | ||
|
Oops, something went wrong.