docker-non-root, bitpanda trading, home for .ssh for ssh-to-signal messages
This commit is contained in:
parent
76801e9f64
commit
73541fd903
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,6 +1,5 @@
|
||||
docker-compose.override.yml
|
||||
htdocs/botdata
|
||||
htdocs/index.html
|
||||
tests
|
||||
.binance-secrets
|
||||
.bitpanda-secrets
|
||||
data/botdata
|
||||
data/index.html
|
||||
dabo/.binance-secrets
|
||||
dabo/.bitpanda-secrets
|
||||
|
@ -3,5 +3,7 @@ RUN apt-get update && \
|
||||
apt-get -y install curl && \
|
||||
curl https://gitea.ds9.dedyn.io/olli/debian.ansible.docker/raw/branch/main/build-debian-env.sh >build-debian-env.sh && \
|
||||
bash -ex build-debian-env.sh
|
||||
RUN addgroup --system --gid 10000 dabo
|
||||
RUN adduser --system --disabled-password --disabled-login --gid 10000 --uid 10000 --home /dabo/home dabo
|
||||
ENV LANG en_US.utf8
|
||||
ENTRYPOINT ["/dabo/dabo-bot.sh"]
|
||||
|
@ -56,7 +56,7 @@ docker -l warn compose --ansi never build --progress=plain --pull --no-cache --f
|
||||
|
||||
Run:
|
||||
```
|
||||
docker-compose down # if on old instance is running
|
||||
docker-compose down # if an old instance is running
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
|
0
dabo/analyze.conf
Normal file → Executable file
0
dabo/analyze.conf
Normal file → Executable file
4
dabo/dabo-bot.conf
Normal file → Executable file
4
dabo/dabo-bot.conf
Normal file → Executable file
@ -9,8 +9,8 @@ FEE="0.4"
|
||||
INTERVAL="150"
|
||||
|
||||
## Currency used for trading
|
||||
CURRENCY="USDT"
|
||||
TRANSFER_CURRENCY="EUR"
|
||||
CURRENCY="EUR"
|
||||
TRANSFER_CURRENCY="NONE"
|
||||
|
||||
# Only use currencies under the first X currencies sorted by market capitalization
|
||||
LARGEST_MARKETCAP="250"
|
||||
|
@ -5,6 +5,8 @@
|
||||
g_lockfile
|
||||
|
||||
|
||||
export LANGUAGE="en_US"
|
||||
|
||||
### CONFIG ###
|
||||
|
||||
BASEPATH=/dabo/htdocs
|
||||
@ -20,6 +22,8 @@ done
|
||||
|
||||
### MAIN ###
|
||||
|
||||
g_signal-notify "STARTING DABO BOT $0"
|
||||
|
||||
# prepare directories
|
||||
mkdir -p ${BASEPATH}/botdata/asset-histories
|
||||
mkdir -p ${BASEPATH}/botdata/trade-histories
|
||||
@ -49,12 +53,13 @@ do
|
||||
# stock data
|
||||
if [ ${STOCK_EXCHANGE} = "BINANCE" ]
|
||||
then
|
||||
#BINANCE_CLI_CMD="docker-compose -f /home/docker/binance-cli/docker-compose.yml exec -T binance-cli binance-cli"
|
||||
# command for current token infos (function for setting var QUANTITY_LOT_CUT
|
||||
TOKEN_INFO_CMD="binance_get_token_info"
|
||||
# command for buying/selling a token
|
||||
#TRADE_CMD="$BINANCE_CLI_CMD ACTION -s TOKEN -u QUANTITY -t market"
|
||||
TRADE_CMD='binance-api-call POST /api/v3/order "&symbol=TOKEN"eOrderQty=QUANTITY&side=ACTION&type=MARKET"'
|
||||
elif [ ${STOCK_EXCHANGE} = "BITPANDA" ]
|
||||
then
|
||||
TRADE_CMD='bitpanda-api-call POST public/v1/account/orders "--header \"Content-Type: application/json\" --data \"{\\\"instrument_code\\\":\\\"TOKEN\\\",\\\"side\\\":\\\"ACTION\\\",\\\"type\\\":\\\"MARKET\\\",\\\"amount\\\":\\\"QUANTITY\\\"}\""'
|
||||
fi
|
||||
|
||||
# Get current assets
|
||||
|
@ -1,14 +0,0 @@
|
||||
function EXCHANGE_GET_ASSETS_CMD {
|
||||
|
||||
if [ ${STOCK_EXCHANGE} = "BINANCE" ]
|
||||
then
|
||||
binance-api-call GET /api/v3/ticker/price || return 1
|
||||
# parse API output
|
||||
cat ${g_tmp}/API_CMD_OUT | jq -r '.[] | .symbol + "," + .price' | grep "${CURRENCY}," | egrep -v "${TRANSFER_CURRENCY},|,0[\.][0]*$" | sort >${f_filename}_OUT.tmp
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ function binance-api-call {
|
||||
local call=$2
|
||||
local params=$3
|
||||
|
||||
if [ -s /home/docker/binance-cli/.binance-secrets ]
|
||||
if [ -s /dabo/.binance-secrets ]
|
||||
then
|
||||
. /home/docker/binance-cli/.binance-secrets
|
||||
. /dabo/.binance-secrets
|
||||
else
|
||||
g_echo_error "No secrets file found"
|
||||
return 1
|
||||
|
@ -129,31 +129,30 @@ ${f_BUY}"
|
||||
|
||||
# remove CURRENCY from asset
|
||||
f_ASSET=$(echo ${f_ASSET} | sed "s/${CURRENCY}//")
|
||||
|
||||
# get stock exchange specific infos for trade (e.g. MIN_NOTIONAL)
|
||||
$TOKEN_INFO_CMD ${f_ASSET} ${CURRENCY}
|
||||
|
||||
# use MIN_NOTIONAL+5% as INVEST_QUANTITY if INVEST_QUANTITY is under MIN_NOTIONAL
|
||||
# +5% in spite of MIN_NOTIONAL to be able to sell when the price falls a little bit
|
||||
[ $(echo "${f_INVEST_QUANTITY} < ${f_MIN_NOTIONAL}" | bc -l) -eq 0 ] || f_INVEST_QUANTITY=$(echo "scale=2; $f_MIN_NOTIONAL/100*105" | bc -l)
|
||||
|
||||
# if there is not enough balance for buying because ${f_MIN_NOTIONAL} needed for buying to sell (workaround)
|
||||
if [ $(echo "${CURRENCY_BALANCE} < ${f_MIN_NOTIONAL}*2" | bc -l) -ne 0 ]
|
||||
then
|
||||
g_echo_note "BUY ${f_ASSET} not enough balance ${CURRENCY_BALANCE} for buying because of MIN_NOTIONAL (${f_MIN_NOTIONAL}*2) needed for buying-to-sell (workaround)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# continue if not balance enough for lowest quantity (MIN_NOTIONAL)
|
||||
if [ $(echo "${CURRENCY_BALANCE} > ${f_INVEST_QUANTITY}" | bc -l) -eq 0 ]
|
||||
then
|
||||
g_echo_note "BUY ${f_ASSET} not enough balance (${CURRENCY_BALANCE}) for lowest quantity (MIN_NOTIONAL - ${f_INVEST_QUANTITY})"
|
||||
return 1
|
||||
fi
|
||||
|
||||
#g_echo_note "BUY BUY BUY ${f_ASSET} ${CURRENCY} ${f_INVEST_QUANTITY} buy \"$f_BUY\""
|
||||
if [ ${STOCK_EXCHANGE} = "BINANCE" ]
|
||||
then
|
||||
# get stock exchange specific infos for trade (e.g. MIN_NOTIONAL)
|
||||
${TOKEN_INFO_CMD} ${f_ASSET} ${CURRENCY}
|
||||
|
||||
# use MIN_NOTIONAL+5% as INVEST_QUANTITY if INVEST_QUANTITY is under MIN_NOTIONAL
|
||||
# +5% in spite of MIN_NOTIONAL to be able to sell when the price falls a little bit
|
||||
[ $(echo "${f_INVEST_QUANTITY} < ${f_MIN_NOTIONAL}" | bc -l) -eq 0 ] || f_INVEST_QUANTITY=$(echo "scale=2; $f_MIN_NOTIONAL/100*105" | bc -l)
|
||||
|
||||
# if there is not enough balance for buying because ${f_MIN_NOTIONAL} needed for buying to sell (workaround)
|
||||
if [ $(echo "${CURRENCY_BALANCE} < ${f_MIN_NOTIONAL}*2" | bc -l) -ne 0 ]
|
||||
then
|
||||
g_echo_note "BUY ${f_ASSET} not enough balance ${CURRENCY_BALANCE} for buying because of MIN_NOTIONAL (${f_MIN_NOTIONAL}*2) needed for buying-to-sell (workaround)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# continue if not balance enough for lowest quantity (MIN_NOTIONAL)
|
||||
if [ $(echo "${CURRENCY_BALANCE} > ${f_INVEST_QUANTITY}" | bc -l) -eq 0 ]
|
||||
then
|
||||
g_echo_note "BUY ${f_ASSET} not enough balance (${CURRENCY_BALANCE}) for lowest quantity (MIN_NOTIONAL - ${f_INVEST_QUANTITY})"
|
||||
return 1
|
||||
fi
|
||||
|
||||
binance_convert ${f_ASSET} ${CURRENCY} ${f_INVEST_QUANTITY} buy "$f_BUY" || \
|
||||
do_trade ${f_ASSET} ${CURRENCY} ${f_INVEST_QUANTITY} buy "$f_BUY"
|
||||
else
|
||||
|
@ -14,21 +14,25 @@ function do_trade {
|
||||
|
||||
local f_link="https://www.coingecko.com/de/munze/$(egrep -i ^${f_ASSET}, COINGECKO_IDS | cut -d, -f2)"
|
||||
|
||||
# get stock exchange specific infos for trade (e.g. f_QUANTITY_LOT_CUT; f_MIN_NOTIONAL)
|
||||
$TOKEN_INFO_CMD $f_ASSET $f_CURRENCY $f_QUANTITY
|
||||
local f_QUANTITY=${f_QUANTITY_LOT_CUT}
|
||||
|
||||
#### Workaround for f_QUANTITY_LOT_CUT by buy more and directly sell
|
||||
g_echo_note "Checking for need of QUANTITY_LOT_CUT Workaround (${f_QUANTITY_LOT_CUT} > ${f_MIN_NOTIONAL})"
|
||||
if [ $(echo "${f_QUANTITY_LOT_CUT} > ${f_MIN_NOTIONAL}" | bc -l) -eq 0 ] && [ ${f_ACTION} = sell ]
|
||||
|
||||
if [ ${STOCK_EXCHANGE} = "BINANCE" ]
|
||||
then
|
||||
# add 0.5 to f_MIN_NOTIONAL and trading fee
|
||||
local f_MIN_NOTIONAL_WITH_FEE=$(echo "${f_MIN_NOTIONAL}+${FEE}+0.5" | bc -l)
|
||||
g_echo_note "Doing QUANTITY_LOT_CUT Workaround - buying ${f_MIN_NOTIONAL_WITH_FEE} ${f_ASSET} ${f_CURRENCY}"
|
||||
do_trade ${f_ASSET} ${f_CURRENCY} ${f_MIN_NOTIONAL_WITH_FEE} buy "Workaround for selling values under QUANTITY_LOT_CUT - buy +MIN_NOTIONAL" || return 1
|
||||
local f_QUANTITY=$(echo "${f_QUANTITY}+${f_MIN_NOTIONAL}" | bc -l)
|
||||
fi
|
||||
# get stock exchange specific infos for trade (e.g. f_QUANTITY_LOT_CUT; f_MIN_NOTIONAL)
|
||||
${TOKEN_INFO_CMD} ${f_ASSET} ${f_CURRENCY} ${f_QUANTITY}
|
||||
local f_QUANTITY=${f_QUANTITY_LOT_CUT}
|
||||
|
||||
#### Workaround for f_QUANTITY_LOT_CUT by buy more and directly sell
|
||||
g_echo_note "Checking for need of QUANTITY_LOT_CUT Workaround (${f_QUANTITY_LOT_CUT} > ${f_MIN_NOTIONAL})"
|
||||
if [ $(echo "${f_QUANTITY_LOT_CUT} > ${f_MIN_NOTIONAL}" | bc -l) -eq 0 ] && [ ${f_ACTION} = sell ]
|
||||
then
|
||||
# add 0.5 to f_MIN_NOTIONAL and trading fee
|
||||
local f_MIN_NOTIONAL_WITH_FEE=$(echo "${f_MIN_NOTIONAL}+${FEE}+0.5" | bc -l)
|
||||
g_echo_note "Doing QUANTITY_LOT_CUT Workaround - buying ${f_MIN_NOTIONAL_WITH_FEE} ${f_ASSET} ${f_CURRENCY}"
|
||||
do_trade ${f_ASSET} ${f_CURRENCY} ${f_MIN_NOTIONAL_WITH_FEE} buy "Workaround for selling values under QUANTITY_LOT_CUT - buy +MIN_NOTIONAL" || return 1
|
||||
local f_QUANTITY=$(echo "${f_QUANTITY}+${f_MIN_NOTIONAL}" | bc -l)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${f_ACTION}" = "buy" ]
|
||||
then
|
||||
# check for enough balance for trade
|
||||
@ -39,15 +43,16 @@ function do_trade {
|
||||
then
|
||||
local f_note="Not enough balance for trade (${f_CURRENCY_BALANCE} > ${f_QUANTITY}) :${f_COMMENT}
|
||||
${FUNCNAME} $@"
|
||||
g_echo_note "$f_note"
|
||||
g_signal-notify "$f_note"
|
||||
g_echo_note "${f_note}"
|
||||
g_signal-notify "${f_note}"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# prepare trading command
|
||||
local f_CMDFILE="trade-histories/${f_DATE}-${f_CURRENCY}-${f_MIN_NOTIONAL}-TRADE_CMD"
|
||||
echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}_${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
# trade
|
||||
g_echo_note "Command: $(cat ${f_CMDFILE})"
|
||||
#g_runcmd g_retrycmd sh ${f_CMDFILE} >${f_CMDFILE}_OUT
|
||||
@ -66,18 +71,20 @@ ${FUNCNAME} $@"
|
||||
sleep 1
|
||||
f_QUANTITY=$(echo "$f_QUANTITY-0.1" | bc -l | sed 's/^\./0./;')
|
||||
g_echo_note "lower $f_QUANTITY by -0.1"
|
||||
echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && echo "${TRADE_CMD}" | perl -pe "s/ACTION/${f_ACTION}/; s/TOKEN/${f_ASSET}_${f_CURRENCY}/; s/QUANTITY/${f_QUANTITY}/" >${f_CMDFILE}
|
||||
#g_runcmd g_retrycmd sh ${f_CMDFILE} >${f_CMDFILE}_OUT
|
||||
. ${f_CMDFILE}
|
||||
cat ${g_tmp}/API_CMD_OUT >${f_CMDFILE}_OUT
|
||||
[ $f_try -eq $f_tries ] && break
|
||||
[ ${f_try} -eq ${f_tries} ] && break
|
||||
((f_try=f_try+1))
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Check return and log trade
|
||||
f_STATUS=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .status)
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && f_STATUS=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .status)
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && f_STATUS=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .order_id)
|
||||
|
||||
local f_trade_info_msg="TRADE - ${f_ACTION} ${f_ASSET}${f_CURRENCY}
|
||||
${f_link}
|
||||
@ -86,12 +93,17 @@ Complete Overview: https://bot.ds9.dedyn.io/
|
||||
|
||||
Comment: ${f_COMMENT}"
|
||||
|
||||
if [ "${f_STATUS}" = "FILLED" ]
|
||||
if [ "${f_STATUS}" = "FILLED" ] || echo ${f_STATUS} | egrep -q '.+-.+-.+-.+'
|
||||
then
|
||||
g_echo_note "TRADE SUCCESSFUL!"
|
||||
local f_PRICE=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].price | head -n1)
|
||||
local f_COMMISSION=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].commission) | head -n1
|
||||
local f_COMMISSIONASSET=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].commissionAsset | head -n1)
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && local f_PRICE=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].price | head -n1)
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && local f_COMMISSION=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].commission) | head -n1
|
||||
[ ${STOCK_EXCHANGE} = "BINANCE" ] && local f_COMMISSIONASSET=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .fills[].commissionAsset | head -n1)
|
||||
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && local f_PRICE=$(cat ${f_CMDFILE}_OUT | grep '^{' | jq -r .price | head -n1)
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && local f_COMMISSION=$(echo "scale=2; $f_PRICE/100*${FEE}" | bc -l)
|
||||
[ ${STOCK_EXCHANGE} = "BITPANDA" ] && local f_COMMISSIONASSET="EUR"
|
||||
|
||||
echo "${f_DATE},${f_ACTION},${f_CMDFILE}_OUT,${f_QUANTITY} ${f_CURRENCY},${f_PRICE},${f_COMMISSION} ${f_COMMISSIONASSET},${f_COMMENT}" | head -n1 >>trade-histories/${f_ASSET}${f_CURRENCY}.history.csv
|
||||
if [ "${f_ACTION}" = "buy" ]
|
||||
then
|
||||
|
@ -11,7 +11,12 @@ function get_assets {
|
||||
binance-api-call GET /api/v3/ticker/price || return 1
|
||||
# parse API output
|
||||
cat ${g_tmp}/API_CMD_OUT | jq -r '.[] | .symbol + "," + .price' | grep "${CURRENCY}," | egrep -v "${TRANSFER_CURRENCY},|,0[\.][0]*$" >${f_filename}_OUT.tmp
|
||||
elif [ ${STOCK_EXCHANGE} = "BITPANDA" ]
|
||||
then
|
||||
bitpanda-api-call GET "public/v1/market-ticker" || return 1
|
||||
cat ${g_tmp}/API_CMD_OUT | jq -r '.[] | .instrument_code + "," + .last_price' | sed 's/_//' | grep "${CURRENCY}," | egrep -v "${TRANSFER_CURRENCY},|,0[\.][0]*$" >${f_filename}_OUT.tmp
|
||||
fi
|
||||
|
||||
# timestamp for data
|
||||
f_timestamp=$(g_date_print)
|
||||
# check output
|
||||
|
@ -11,6 +11,10 @@ function get_balances {
|
||||
binance-api-call GET sapi/v1/capital/config/getall || return 1
|
||||
# parse outout
|
||||
cat ${g_tmp}/API_CMD_OUT | jq -r '.[] | .coin + "," + .free' | egrep -v ",0$|,0[\.][0]*$|${TRANSFER_CURRENCY}" | sort >${f_filename}_OUT.tmp_raw
|
||||
elif [ ${STOCK_EXCHANGE} = "BITPANDA" ]
|
||||
then
|
||||
bitpanda-api-call GET public/v1/account/balances || return 1
|
||||
cat ${g_tmp}/API_CMD_OUT | jq -r '.balances[] | .currency_code + "," + .available' | egrep -v ",0$|,0[\.][0]*$|${TRANSFER_CURRENCY}" | sort >${f_filename}_OUT.tmp_raw
|
||||
fi
|
||||
|
||||
if ! [ -s ${f_filename}_OUT.tmp_raw ] && egrep -q "^[A-Z]+,[0-9]*\.[0-9]+$" ${f_filename}_OUT.tmp_raw
|
||||
|
@ -58,7 +58,7 @@ function market_performance {
|
||||
#local f_back=240
|
||||
#[[ $(date +%u) -eq 6 ]] && f_back=1500
|
||||
#[[ $(date +%u) -eq 7 ]] && f_back=2940
|
||||
local f_from=$(tail -n 10080 asset-histories/MSCI-WORLD-INDEX.history.csv | grep -v ^[A-Z] | head -n1 | cut -d, -f2)
|
||||
local f_from=$(tail -n 1440 asset-histories/MSCI-WORLD-INDEX.history.csv | grep -v ^[A-Z] | head -n1 | cut -d, -f2)
|
||||
local f_to=$(tail -n 1 asset-histories/MSCI-WORLD-INDEX.history.csv | cut -d, -f2)
|
||||
local f_exchange_rate_diff_percentage=$(g_percentage-diff ${f_from} ${f_to})
|
||||
#local f_back=10080
|
||||
|
@ -194,7 +194,7 @@ function webpage {
|
||||
|
||||
|
||||
echo "<h2>Current config</h2>" >>../index.html.tmp
|
||||
echo "<pre>$(cat ../../bot.conf | perl -pe 's/\</</g; s/\>/>/g;')</pre>" >>../index.html.tmp
|
||||
echo "<pre>$(cat ../../dabo-bot.conf | perl -pe 's/\</</g; s/\>/>/g;')</pre>" >>../index.html.tmp
|
||||
|
||||
|
||||
|
||||
|
@ -6,9 +6,12 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
user: 10000:10000
|
||||
volumes:
|
||||
- ./dabo:/dabo:ro
|
||||
- ./data:/dabo/htdocs:rw
|
||||
- ./home:/dabo/home:rw
|
||||
- /usr/local/bin/notify.sh:/usr/local/bin/notify.sh:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
networks:
|
||||
- dabo--network
|
||||
|
Loading…
Reference in New Issue
Block a user