Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
joakimhellum committed Nov 17, 2024
1 parent 33fc1f7 commit 13c94ec
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 116 deletions.
7 changes: 4 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
all:
make deps shellcheck test build
all: clean deps shellcheck test build
deps:
@wget https://raw.githubusercontent.com/system4-tech/utils-sh/refs/heads/main/lib/utils.sh -O lib/utils.sh
@wget https://raw.githubusercontent.com/system4-tech/utils-sh/refs/heads/main/lib/utils.sh -qO lib/utils.sh
build:
@awk -f inline.awk src/main.sh > lib/binance.sh
clean:
@rm lib/*.sh
test:
@bats tests/*.bats
shellcheck:
Expand Down
26 changes: 23 additions & 3 deletions examples/klines.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,37 @@

set -eu

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"

. "$SCRIPT_DIR/../lib/binance.sh"

main() {
local symbols
local symbols start_time
local klines open high low close
local -a kline

symbols=$(symbols spot)
start_time=$(today)

for symbol in $symbols; do
klines spot $symbol 1d 2021-01-01 2021-01-02
klines=$(klines spot $symbol 1d $start_time | jq -c .[])

for kline in $klines; do
readarray -t kline < <(jq -r .[] <<< $kline)

open_time=${kline[0]}
open=${kline[1]}
high=${kline[2]}
low=${kline[3]}
close=${kline[4]}
close_time=${kline[6]}

if is_set $open; then
echo "Symbol: $symbol, Open: $open, High: $high"
fi

done

done
}

Expand Down
120 changes: 94 additions & 26 deletions lib/binance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,8 @@ _http() {

curl "$url" "$@" \
--request "$method" \
--fail \
--fail-with-body \
--silent \
--show-error \
--location \
--retry-connrefused \
--max-time "${HTTP_MAX_TIME:-180}" \
Expand Down Expand Up @@ -230,6 +229,51 @@ date_to_ms() {
date -d "$date" +%s%3N
}

#######################################
# Gets today's date in YYYY-MM-DD format.
# Globals:
# None
# Arguments:
# None
# Outputs:
# Writes today's date to stdout
# Returns:
# 0 on success
#######################################
today() {
date +%F
}

#######################################
# Gets yesterday's date in YYYY-MM-DD format.
# Globals:
# None
# Arguments:
# None
# Outputs:
# Writes yesterday's date to stdout
# Returns:
# 0 on success
#######################################
yesterday() {
date -d "yesterday" +%F
}

#######################################
# Gets tomorrow's date in YYYY-MM-DD format.
# Globals:
# None
# Arguments:
# None
# Outputs:
# Writes tomorrow's date to stdout
# Returns:
# 0 on success
#######################################
tomorrow() {
date -d "tomorrow" +%F
}

#######################################
# Checks if the provided argument is set (non-empty).
# Globals:
Expand Down Expand Up @@ -272,6 +316,22 @@ is_empty() {
fi
}

#######################################
# Prints an error message to stderr and exits the script.
# Globals:
# None
# Arguments:
# message (string): The error message to display.
# Outputs:
# Writes the error message to stderr.
# Returns:
# Exits the script with a status code of 1.
#######################################
fail() {
local message="$*"
echo "$message" >&2
exit 1
}

declare -Ag API_URLS

Expand All @@ -281,6 +341,28 @@ API_URLS=(
[um]=https://fapi.binance.com/fapi/v1 # USD-M Futures
)

#######################################
# Retrieves available symbols for a given product.
# Globals:
# API_URLS (associative array of API URLs per product)
# Arguments:
# product (string): Product key used to select base URL.
# Outputs:
# A list of symbols in plain text, one per line.
# Returns:
# 0 on success, non-zero on error.
#######################################
symbols() {
local product base_url

product=${1:?missing required <product> argument}

base_url=${API_URLS[$product]:?API URL is not set}

# todo: check response before passing to jq
http.get "${base_url}/exchangeInfo" | jq -r .symbols[].symbol
}

#######################################
# Retrieves kline (candlestick) data for a specific symbol and interval.
# Globals:
Expand Down Expand Up @@ -310,38 +392,24 @@ klines() {
base_url=${API_URLS[$product]:?API URL is not set}
query_string="symbol=${symbol}&interval=${interval}&limit=1000"

if is_set "$start_time" && is_date "$start_time"; then
if is_set "$start_time"; then
if ! is_date "$start_time"; then
fail "<start_time> must be valid date"
fi

start_time_ms=$(date_to_ms "$start_time")
query_string+="&startTime=${start_time_ms}"
fi

if is_set "$end_time" && is_date "$end_time"; then
if is_set "$end_time"; then
if ! is_date "$end_time"; then
fail "<end_time> must be valid date"
fi

end_time_ms=$(date_to_ms "$end_time")
query_string+="&endTime=${end_time_ms}"
fi

# todo: check response before passing to jq
http.get "${base_url}/klines?${query_string}" | jq -r .
}

#######################################
# Retrieves available symbols for a given product.
# Globals:
# API_URLS (associative array of API URLs per product)
# Arguments:
# product (string): Product key used to select base URL.
# Outputs:
# A list of symbols in plain text, one per line.
# Returns:
# 0 on success, non-zero on error.
#######################################
symbols() {
local product base_url

product=${1:?missing required <product> argument}

base_url=${API_URLS[$product]:?API URL is not set}

# todo: check response before passing to jq
http.get "${base_url}/exchangeInfo" | jq -r .symbols[].symbol
}
9 changes: 0 additions & 9 deletions src/api_urls.sh

This file was deleted.

44 changes: 0 additions & 44 deletions src/klines.sh

This file was deleted.

85 changes: 81 additions & 4 deletions src/main.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,84 @@
#!/usr/bin/env bash

. ../lib/utils.sh # run `make deps` first
. ../lib/utils.sh

. api_urls.sh
. klines.sh
. ./symbols.sh # fix: find out why awk won't interpret 'symbols.sh'
declare -Ag API_URLS

API_URLS=(
[spot]=https://api.binance.com/api/v3
[cm]=https://dapi.binance.com/dapi/v1 # COIN-M Futures
[um]=https://fapi.binance.com/fapi/v1 # USD-M Futures
)

#######################################
# Retrieves available symbols for a given product.
# Globals:
# API_URLS (associative array of API URLs per product)
# Arguments:
# product (string): Product key used to select base URL.
# Outputs:
# A list of symbols in plain text, one per line.
# Returns:
# 0 on success, non-zero on error.
#######################################
symbols() {
local product base_url

product=${1:?missing required <product> argument}

base_url=${API_URLS[$product]:?API URL is not set}

# todo: check response before passing to jq
http.get "${base_url}/exchangeInfo" | jq -r .symbols[].symbol
}

#######################################
# Retrieves kline (candlestick) data for a specific symbol and interval.
# Globals:
# API_URLS (associative array of API URLs per product)
# Arguments:
# product (string): Product key used to select base URL.
# symbol (string): Trading symbol (e.g., BTCUSDT).
# interval (string): Kline interval (e.g., 1m, 1h, 1d).
# start_time (string, optional): Start date in format 'YYYY-MM-DD'.
# end_time (string, optional): End date in format 'YYYY-MM-DD'.
# Outputs:
# JSON array of kline data.
# Returns:
# 0 on success, non-zero on error.
#######################################
klines() {
local product symbol interval start_time end_time
local base_url query_string
local start_time_ms end_time_ms

product=${1:?missing required <product> argument}
symbol=${2:?missing required <symbol> argument}
interval=${3:?missing required <interval> argument}
start_time=${4:-}
end_time=${5:-}

base_url=${API_URLS[$product]:?API URL is not set}
query_string="symbol=${symbol}&interval=${interval}&limit=1000"

if is_set "$start_time"; then
if ! is_date "$start_time"; then
fail "<start_time> must be valid date"
fi

start_time_ms=$(date_to_ms "$start_time")
query_string+="&startTime=${start_time_ms}"
fi

if is_set "$end_time"; then
if ! is_date "$end_time"; then
fail "<end_time> must be valid date"
fi

end_time_ms=$(date_to_ms "$end_time")
query_string+="&endTime=${end_time_ms}"
fi

# todo: check response before passing to jq
http.get "${base_url}/klines?${query_string}" | jq -r .
}
23 changes: 0 additions & 23 deletions src/symbols.sh

This file was deleted.

Loading

0 comments on commit 13c94ec

Please sign in to comment.