Merge branch 'develop' into margin-db
This commit is contained in:
commit
661bec1b5f
@ -1,11 +1,20 @@
|
||||
{
|
||||
"name": "freqtrade Develop",
|
||||
|
||||
"dockerComposeFile": [
|
||||
"docker-compose.yml"
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".."
|
||||
},
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
8080
|
||||
],
|
||||
"mounts": [
|
||||
"source=freqtrade-bashhistory,target=/home/ftuser/commandhistory,type=volume"
|
||||
],
|
||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "ftuser",
|
||||
|
||||
"service": "ft_vscode",
|
||||
"postCreateCommand": "freqtrade create-userdir --userdir user_data/",
|
||||
|
||||
"workspaceFolder": "/freqtrade/",
|
||||
|
||||
@ -25,20 +34,6 @@
|
||||
"ms-python.vscode-pylance",
|
||||
"davidanson.vscode-markdownlint",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Uncomment the next line if you want start specific services in your Docker Compose config.
|
||||
// "runServices": [],
|
||||
|
||||
// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
|
||||
// "shutdownAction": "none",
|
||||
|
||||
// Uncomment the next line to run commands after the container is created - for example installing curl.
|
||||
// "postCreateCommand": "sudo apt-get update && apt-get install -y git",
|
||||
|
||||
// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "ftuser"
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
---
|
||||
version: '3'
|
||||
services:
|
||||
ft_vscode:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: ".devcontainer/Dockerfile"
|
||||
volumes:
|
||||
# Allow git usage within container
|
||||
- "${HOME}/.ssh:/home/ftuser/.ssh:ro"
|
||||
- "${HOME}/.gitconfig:/home/ftuser/.gitconfig:ro"
|
||||
- ..:/freqtrade:cached
|
||||
# Persist bash-history
|
||||
- freqtrade-vscode-server:/home/ftuser/.vscode-server
|
||||
- freqtrade-bashhistory:/home/ftuser/commandhistory
|
||||
# Expose API port
|
||||
ports:
|
||||
- "127.0.0.1:8080:8080"
|
||||
command: /bin/sh -c "while sleep 1000; do :; done"
|
||||
|
||||
|
||||
volumes:
|
||||
freqtrade-vscode-server:
|
||||
freqtrade-bashhistory:
|
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -79,13 +79,13 @@ jobs:
|
||||
|
||||
- name: Backtesting
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
||||
|
||||
- name: Hyperopt
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||
|
||||
@ -172,13 +172,13 @@ jobs:
|
||||
|
||||
- name: Backtesting
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
||||
|
||||
- name: Hyperopt
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||
|
||||
@ -239,13 +239,13 @@ jobs:
|
||||
|
||||
- name: Backtesting
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
||||
|
||||
- name: Hyperopt
|
||||
run: |
|
||||
cp config_bittrex.json.example config.json
|
||||
cp config_examples/config_bittrex.example.json config.json
|
||||
freqtrade create-userdir --userdir user_data
|
||||
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all
|
||||
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -95,3 +95,8 @@ target/
|
||||
|
||||
#exceptions
|
||||
!*.gitkeep
|
||||
!config_examples/config_binance.example.json
|
||||
!config_examples/config_bittrex.example.json
|
||||
!config_examples/config_ftx.example.json
|
||||
!config_examples/config_full.example.json
|
||||
!config_examples/config_kraken.example.json
|
||||
|
@ -26,12 +26,12 @@ jobs:
|
||||
# - coveralls || true
|
||||
name: pytest
|
||||
- script:
|
||||
- cp config_bittrex.json.example config.json
|
||||
- cp config_examples/config_bittrex.example.json config.json
|
||||
- freqtrade create-userdir --userdir user_data
|
||||
- freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
|
||||
name: backtest
|
||||
- script:
|
||||
- cp config_bittrex.json.example config.json
|
||||
- cp config_examples/config_bittrex.example.json config.json
|
||||
- freqtrade create-userdir --userdir user_data
|
||||
- freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily
|
||||
name: hyperopt
|
||||
|
@ -52,7 +52,7 @@ docker build --cache-from freqtrade:${TAG} --build-arg sourceimage=${TAG} -t fre
|
||||
docker tag freqtrade:$TAG_PLOT ${IMAGE_NAME}:$TAG_PLOT
|
||||
|
||||
# Run backtest
|
||||
docker run --rm -v $(pwd)/config_bittrex.json.example:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy DefaultStrategy
|
||||
docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy DefaultStrategy
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "failed running backtest"
|
||||
|
@ -573,7 +573,7 @@ You should also make sure to read the [Exchanges](exchanges.md) section of the d
|
||||
|
||||
To use a proxy with freqtrade, add the kwarg `"aiohttp_trust_env"=true` to the `"ccxt_async_kwargs"` dict in the exchange section of the configuration.
|
||||
|
||||
An example for this can be found in `config_full.json.example`
|
||||
An example for this can be found in `config_examples/config_full.example.json`
|
||||
|
||||
``` json
|
||||
"ccxt_async_config": {
|
||||
|
@ -245,10 +245,10 @@ current max
|
||||
Return a summary of your profit/loss and performance.
|
||||
|
||||
> **ROI:** Close trades
|
||||
> ∙ `0.00485701 BTC (258.45%)`
|
||||
> ∙ `0.00485701 BTC (2.2%) (15.2 Σ%)`
|
||||
> ∙ `62.968 USD`
|
||||
> **ROI:** All trades
|
||||
> ∙ `0.00255280 BTC (143.43%)`
|
||||
> ∙ `0.00255280 BTC (1.5%) (6.43 Σ%)`
|
||||
> ∙ `33.095 EUR`
|
||||
>
|
||||
> **Total Trade Count:** `138`
|
||||
@ -257,6 +257,10 @@ Return a summary of your profit/loss and performance.
|
||||
> **Avg. Duration:** `2:33:45`
|
||||
> **Best Performing:** `PAY/BTC: 50.23%`
|
||||
|
||||
The relative profit of `1.2%` is the average profit per trade.
|
||||
The relative profit of `15.2 Σ%` is be based on the starting capital - so in this case, the starting capital was `0.00485701 * 1.152 = 0.00738 BTC`.
|
||||
Starting capital is either taken from the `available_capital` setting, or calculated by using current wallet size - profits.
|
||||
|
||||
### /forcesell <trade_id>
|
||||
|
||||
> **BITTREX:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)`
|
||||
|
@ -67,12 +67,16 @@ class Profit(BaseModel):
|
||||
profit_closed_ratio_mean: float
|
||||
profit_closed_percent_sum: float
|
||||
profit_closed_ratio_sum: float
|
||||
profit_closed_percent: float
|
||||
profit_closed_ratio: float
|
||||
profit_closed_fiat: float
|
||||
profit_all_coin: float
|
||||
profit_all_percent_mean: float
|
||||
profit_all_ratio_mean: float
|
||||
profit_all_percent_sum: float
|
||||
profit_all_ratio_sum: float
|
||||
profit_all_percent: float
|
||||
profit_all_ratio: float
|
||||
profit_all_fiat: float
|
||||
trade_count: int
|
||||
closed_trade_count: int
|
||||
@ -115,6 +119,7 @@ class ShowConfig(BaseModel):
|
||||
dry_run: bool
|
||||
stake_currency: str
|
||||
stake_amount: Union[float, str]
|
||||
available_capital: Optional[float]
|
||||
stake_currency_decimals: int
|
||||
max_open_trades: int
|
||||
minimal_roi: Dict[str, Any]
|
||||
|
@ -106,6 +106,7 @@ class RPC:
|
||||
'stake_currency': config['stake_currency'],
|
||||
'stake_currency_decimals': decimals_per_coin(config['stake_currency']),
|
||||
'stake_amount': config['stake_amount'],
|
||||
'available_capital': config.get('available_capital'),
|
||||
'max_open_trades': (config['max_open_trades']
|
||||
if config['max_open_trades'] != float('inf') else -1),
|
||||
'minimal_roi': config['minimal_roi'].copy() if 'minimal_roi' in config else {},
|
||||
@ -396,7 +397,12 @@ class RPC:
|
||||
|
||||
profit_all_coin_sum = round(sum(profit_all_coin), 8)
|
||||
profit_all_ratio_mean = float(mean(profit_all_ratio) if profit_all_ratio else 0.0)
|
||||
# Doing the sum is not right - overall profit needs to be based on initial capital
|
||||
profit_all_ratio_sum = sum(profit_all_ratio) if profit_all_ratio else 0.0
|
||||
starting_balance = self._freqtrade.wallets.get_starting_balance()
|
||||
profit_closed_ratio_fromstart = profit_closed_coin_sum / starting_balance
|
||||
profit_all_ratio_fromstart = profit_all_coin_sum / starting_balance
|
||||
|
||||
profit_all_fiat = self._fiat_converter.convert_amount(
|
||||
profit_all_coin_sum,
|
||||
stake_currency,
|
||||
@ -412,12 +418,16 @@ class RPC:
|
||||
'profit_closed_ratio_mean': profit_closed_ratio_mean,
|
||||
'profit_closed_percent_sum': round(profit_closed_ratio_sum * 100, 2),
|
||||
'profit_closed_ratio_sum': profit_closed_ratio_sum,
|
||||
'profit_closed_ratio': profit_closed_ratio_fromstart,
|
||||
'profit_closed_percent': round(profit_closed_ratio_fromstart * 100, 2),
|
||||
'profit_closed_fiat': profit_closed_fiat,
|
||||
'profit_all_coin': profit_all_coin_sum,
|
||||
'profit_all_percent_mean': round(profit_all_ratio_mean * 100, 2),
|
||||
'profit_all_ratio_mean': profit_all_ratio_mean,
|
||||
'profit_all_percent_sum': round(profit_all_ratio_sum * 100, 2),
|
||||
'profit_all_ratio_sum': profit_all_ratio_sum,
|
||||
'profit_all_ratio': profit_all_ratio_fromstart,
|
||||
'profit_all_percent': round(profit_all_ratio_fromstart * 100, 2),
|
||||
'profit_all_fiat': profit_all_fiat,
|
||||
'trade_count': len(trades),
|
||||
'closed_trade_count': len([t for t in trades if not t.is_open]),
|
||||
|
@ -494,11 +494,11 @@ class Telegram(RPCHandler):
|
||||
start_date)
|
||||
profit_closed_coin = stats['profit_closed_coin']
|
||||
profit_closed_percent_mean = stats['profit_closed_percent_mean']
|
||||
profit_closed_percent_sum = stats['profit_closed_percent_sum']
|
||||
profit_closed_percent = stats['profit_closed_percent']
|
||||
profit_closed_fiat = stats['profit_closed_fiat']
|
||||
profit_all_coin = stats['profit_all_coin']
|
||||
profit_all_percent_mean = stats['profit_all_percent_mean']
|
||||
profit_all_percent_sum = stats['profit_all_percent_sum']
|
||||
profit_all_percent = stats['profit_all_percent']
|
||||
profit_all_fiat = stats['profit_all_fiat']
|
||||
trade_count = stats['trade_count']
|
||||
first_trade_date = stats['first_trade_date']
|
||||
@ -514,7 +514,7 @@ class Telegram(RPCHandler):
|
||||
markdown_msg = ("*ROI:* Closed trades\n"
|
||||
f"∙ `{round_coin_value(profit_closed_coin, stake_cur)} "
|
||||
f"({profit_closed_percent_mean:.2f}%) "
|
||||
f"({profit_closed_percent_sum} \N{GREEK CAPITAL LETTER SIGMA}%)`\n"
|
||||
f"({profit_closed_percent} \N{GREEK CAPITAL LETTER SIGMA}%)`\n"
|
||||
f"∙ `{round_coin_value(profit_closed_fiat, fiat_disp_cur)}`\n")
|
||||
else:
|
||||
markdown_msg = "`No closed trade` \n"
|
||||
@ -523,7 +523,7 @@ class Telegram(RPCHandler):
|
||||
f"*ROI:* All trades\n"
|
||||
f"∙ `{round_coin_value(profit_all_coin, stake_cur)} "
|
||||
f"({profit_all_percent_mean:.2f}%) "
|
||||
f"({profit_all_percent_sum} \N{GREEK CAPITAL LETTER SIGMA}%)`\n"
|
||||
f"({profit_all_percent} \N{GREEK CAPITAL LETTER SIGMA}%)`\n"
|
||||
f"∙ `{round_coin_value(profit_all_fiat, fiat_disp_cur)}`\n"
|
||||
f"*Total Trade Count:* `{trade_count}`\n"
|
||||
f"*{'First Trade opened' if not timescale else 'Showing Profit since'}:* "
|
||||
|
@ -129,6 +129,19 @@ class Wallets:
|
||||
def get_all_balances(self) -> Dict[str, Any]:
|
||||
return self._wallets
|
||||
|
||||
def get_starting_balance(self) -> float:
|
||||
"""
|
||||
Retrieves starting balance - based on either available capital,
|
||||
or by using current balance subtracting
|
||||
"""
|
||||
if "available_capital" in self._config:
|
||||
return self._config['available_capital']
|
||||
else:
|
||||
tot_profit = Trade.get_total_closed_profit()
|
||||
open_stakes = Trade.total_open_trades_stakes()
|
||||
available_balance = self.get_free(self._config['stake_currency'])
|
||||
return available_balance - tot_profit + open_stakes
|
||||
|
||||
def get_total_stake_amount(self):
|
||||
"""
|
||||
Return the total currently available balance in stake currency, including tied up stake and
|
||||
@ -233,18 +246,21 @@ class Wallets:
|
||||
max_stake_amount = self.get_available_stake_amount()
|
||||
|
||||
if min_stake_amount > max_stake_amount:
|
||||
logger.warning("Minimum stake amount > available balance.")
|
||||
if self._log:
|
||||
logger.warning("Minimum stake amount > available balance.")
|
||||
return 0
|
||||
if min_stake_amount is not None and stake_amount < min_stake_amount:
|
||||
stake_amount = min_stake_amount
|
||||
logger.info(
|
||||
f"Stake amount for pair {pair} is too small ({stake_amount} < {min_stake_amount}), "
|
||||
f"adjusting to {min_stake_amount}."
|
||||
)
|
||||
if self._log:
|
||||
logger.info(
|
||||
f"Stake amount for pair {pair} is too small "
|
||||
f"({stake_amount} < {min_stake_amount}), adjusting to {min_stake_amount}."
|
||||
)
|
||||
if stake_amount > max_stake_amount:
|
||||
stake_amount = max_stake_amount
|
||||
logger.info(
|
||||
f"Stake amount for pair {pair} is too big ({stake_amount} > {max_stake_amount}), "
|
||||
f"adjusting to {max_stake_amount}."
|
||||
)
|
||||
if self._log:
|
||||
logger.info(
|
||||
f"Stake amount for pair {pair} is too big "
|
||||
f"({stake_amount} > {max_stake_amount}), adjusting to {max_stake_amount}."
|
||||
)
|
||||
return stake_amount
|
||||
|
78
setup.sh
78
setup.sh
@ -17,35 +17,20 @@ function check_installed_python() {
|
||||
exit 2
|
||||
fi
|
||||
|
||||
which python3.8
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "using Python 3.8"
|
||||
PYTHON=python3.8
|
||||
check_installed_pip
|
||||
return
|
||||
fi
|
||||
for v in 8 9 7
|
||||
do
|
||||
PYTHON="python3.${v}"
|
||||
which $PYTHON
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "using ${PYTHON}"
|
||||
|
||||
which python3.9
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "using Python 3.9"
|
||||
PYTHON=python3.9
|
||||
check_installed_pip
|
||||
return
|
||||
fi
|
||||
check_installed_pip
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
||||
which python3.7
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "using Python 3.7"
|
||||
PYTHON=python3.7
|
||||
check_installed_pip
|
||||
return
|
||||
fi
|
||||
|
||||
|
||||
if [ -z ${PYTHON} ]; then
|
||||
echo "No usable python found. Please make sure to have python3.7 or newer installed"
|
||||
exit 1
|
||||
fi
|
||||
echo "No usable python found. Please make sure to have python3.7 or newer installed"
|
||||
exit 1
|
||||
}
|
||||
|
||||
function updateenv() {
|
||||
@ -122,6 +107,25 @@ function install_talib() {
|
||||
cd ..
|
||||
}
|
||||
|
||||
function install_mac_newer_python_dependencies() {
|
||||
|
||||
if [ ! $(brew --prefix --installed hdf5 2>/dev/null) ]
|
||||
then
|
||||
echo "-------------------------"
|
||||
echo "Installing hdf5"
|
||||
echo "-------------------------"
|
||||
brew install hdf5
|
||||
fi
|
||||
|
||||
if [ ! $(brew --prefix --installed c-blosc 2>/dev/null) ]
|
||||
then
|
||||
echo "-------------------------"
|
||||
echo "Installing c-blosc"
|
||||
echo "-------------------------"
|
||||
brew install c-blosc
|
||||
fi
|
||||
}
|
||||
|
||||
# Install bot MacOS
|
||||
function install_macos() {
|
||||
if [ ! -x "$(command -v brew)" ]
|
||||
@ -131,8 +135,13 @@ function install_macos() {
|
||||
echo "-------------------------"
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
fi
|
||||
#Gets number after decimal in python version
|
||||
version=$(egrep -o 3.\[0-9\]+ <<< $PYTHON | sed 's/3.//g' )
|
||||
|
||||
if [[ $version -ge 9 ]]; then #Checks if python version >= 3.9
|
||||
install_mac_newer_python_dependencies
|
||||
fi
|
||||
install_talib
|
||||
test_and_fix_python_on_mac
|
||||
}
|
||||
|
||||
# Install bot Debian_ubuntu
|
||||
@ -189,19 +198,6 @@ function reset() {
|
||||
updateenv
|
||||
}
|
||||
|
||||
function test_and_fix_python_on_mac() {
|
||||
|
||||
if ! [ -x "$(command -v python3.6)" ]
|
||||
then
|
||||
echo "-------------------------"
|
||||
echo "Fixing Python"
|
||||
echo "-------------------------"
|
||||
echo "Python 3.6 is not linked in your system. Fixing it..."
|
||||
brew link --overwrite python
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
function config() {
|
||||
|
||||
echo "-------------------------"
|
||||
|
@ -26,7 +26,7 @@ from tests.conftest_trades import MOCK_TRADE_COUNT
|
||||
|
||||
def test_setup_utils_configuration():
|
||||
args = [
|
||||
'list-exchanges', '--config', 'config_bittrex.json.example',
|
||||
'list-exchanges', '--config', 'config_examples/config_bittrex.example.json',
|
||||
]
|
||||
|
||||
config = setup_utils_configuration(get_args(args), RunMode.OTHER)
|
||||
@ -45,7 +45,7 @@ def test_start_trading_fail(mocker, caplog):
|
||||
exitmock = mocker.patch("freqtrade.worker.Worker.exit", MagicMock())
|
||||
args = [
|
||||
'trade',
|
||||
'-c', 'config_bittrex.json.example'
|
||||
'-c', 'config_examples/config_bittrex.example.json'
|
||||
]
|
||||
start_trading(get_args(args))
|
||||
assert exitmock.call_count == 1
|
||||
@ -127,10 +127,10 @@ def test_list_timeframes(mocker, capsys):
|
||||
match=r"This command requires a configured exchange.*"):
|
||||
start_list_timeframes(pargs)
|
||||
|
||||
# Test with --config config_bittrex.json.example
|
||||
# Test with --config config_examples/config_bittrex.example.json
|
||||
args = [
|
||||
"list-timeframes",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
]
|
||||
start_list_timeframes(get_args(args))
|
||||
captured = capsys.readouterr()
|
||||
@ -174,7 +174,7 @@ def test_list_timeframes(mocker, capsys):
|
||||
# Test with --one-column
|
||||
args = [
|
||||
"list-timeframes",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--one-column",
|
||||
]
|
||||
start_list_timeframes(get_args(args))
|
||||
@ -214,10 +214,10 @@ def test_list_markets(mocker, markets, capsys):
|
||||
match=r"This command requires a configured exchange.*"):
|
||||
start_list_markets(pargs, False)
|
||||
|
||||
# Test with --config config_bittrex.json.example
|
||||
# Test with --config config_examples/config_bittrex.example.json
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-list",
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -244,7 +244,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test with --all: all markets
|
||||
args = [
|
||||
"list-markets", "--all",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-list",
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -257,7 +257,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test list-pairs subcommand: active pairs
|
||||
args = [
|
||||
"list-pairs",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-list",
|
||||
]
|
||||
start_list_markets(get_args(args), True)
|
||||
@ -269,7 +269,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test list-pairs subcommand with --all: all pairs
|
||||
args = [
|
||||
"list-pairs", "--all",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-list",
|
||||
]
|
||||
start_list_markets(get_args(args), True)
|
||||
@ -282,7 +282,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, base=ETH, LTC
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "ETH", "LTC",
|
||||
"--print-list",
|
||||
]
|
||||
@ -295,7 +295,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, base=LTC
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC",
|
||||
"--print-list",
|
||||
]
|
||||
@ -308,7 +308,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, quote=USDT, USD
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--quote", "USDT", "USD",
|
||||
"--print-list",
|
||||
]
|
||||
@ -321,7 +321,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, quote=USDT
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--quote", "USDT",
|
||||
"--print-list",
|
||||
]
|
||||
@ -334,7 +334,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, base=LTC, quote=USDT
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC", "--quote", "USDT",
|
||||
"--print-list",
|
||||
]
|
||||
@ -347,7 +347,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active pairs, base=LTC, quote=USDT
|
||||
args = [
|
||||
"list-pairs",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC", "--quote", "USD",
|
||||
"--print-list",
|
||||
]
|
||||
@ -360,7 +360,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, base=LTC, quote=USDT, NONEXISTENT
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC", "--quote", "USDT", "NONEXISTENT",
|
||||
"--print-list",
|
||||
]
|
||||
@ -373,7 +373,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# active markets, base=LTC, quote=NONEXISTENT
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC", "--quote", "NONEXISTENT",
|
||||
"--print-list",
|
||||
]
|
||||
@ -386,7 +386,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test tabular output
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
captured = capsys.readouterr()
|
||||
@ -396,7 +396,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test tabular output, no markets found
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--base", "LTC", "--quote", "NONEXISTENT",
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -408,7 +408,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test --print-json
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-json"
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -420,7 +420,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test --print-csv
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--print-csv"
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -432,7 +432,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test --one-column
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--one-column"
|
||||
]
|
||||
start_list_markets(get_args(args), False)
|
||||
@ -444,7 +444,7 @@ def test_list_markets(mocker, markets, capsys):
|
||||
# Test --one-column
|
||||
args = [
|
||||
"list-markets",
|
||||
'--config', 'config_bittrex.json.example',
|
||||
'--config', 'config_examples/config_bittrex.example.json',
|
||||
"--one-column"
|
||||
]
|
||||
with pytest.raises(OperationalException, match=r"Cannot get markets.*"):
|
||||
@ -887,7 +887,7 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
|
||||
patched_configuration_load_config_file(mocker, default_conf)
|
||||
args = [
|
||||
'test-pairlist',
|
||||
'-c', 'config_bittrex.json.example'
|
||||
'-c', 'config_examples/config_bittrex.example.json'
|
||||
]
|
||||
|
||||
start_test_pairlist(get_args(args))
|
||||
@ -901,7 +901,7 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
|
||||
|
||||
args = [
|
||||
'test-pairlist',
|
||||
'-c', 'config_bittrex.json.example',
|
||||
'-c', 'config_examples/config_bittrex.example.json',
|
||||
'--one-column',
|
||||
]
|
||||
start_test_pairlist(get_args(args))
|
||||
@ -910,7 +910,7 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
|
||||
|
||||
args = [
|
||||
'test-pairlist',
|
||||
'-c', 'config_bittrex.json.example',
|
||||
'-c', 'config_examples/config_bittrex.example.json',
|
||||
'--print-json',
|
||||
]
|
||||
start_test_pairlist(get_args(args))
|
||||
|
@ -677,12 +677,16 @@ def test_api_profit(botclient, mocker, ticker, fee, markets):
|
||||
'profit_all_ratio_mean': -0.6641100666666667,
|
||||
'profit_all_percent_sum': -398.47,
|
||||
'profit_all_ratio_sum': -3.9846604,
|
||||
'profit_all_percent': -4.41,
|
||||
'profit_all_ratio': -0.044063014216106644,
|
||||
'profit_closed_coin': 0.00073913,
|
||||
'profit_closed_fiat': 9.124559849999999,
|
||||
'profit_closed_ratio_mean': 0.0075,
|
||||
'profit_closed_percent_mean': 0.75,
|
||||
'profit_closed_ratio_sum': 0.015,
|
||||
'profit_closed_percent_sum': 1.5,
|
||||
'profit_closed_ratio': 7.391275897987988e-07,
|
||||
'profit_closed_percent': 0.0,
|
||||
'trade_count': 6,
|
||||
'closed_trade_count': 2,
|
||||
'winning_trades': 2,
|
||||
|
@ -452,7 +452,8 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
assert msg_mock.call_count == 1
|
||||
assert 'No closed trade' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert ('∙ `-0.00000500 BTC (-0.50%) (-0.5 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
mocker.patch('freqtrade.wallets.Wallets.get_starting_balance', return_value=0.01)
|
||||
assert ('∙ `-0.00000500 BTC (-0.50%) (-0.0 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
msg_mock.reset_mock()
|
||||
|
||||
@ -466,11 +467,11 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
|
||||
telegram._profit(update=update, context=MagicMock())
|
||||
assert msg_mock.call_count == 1
|
||||
assert '*ROI:* Closed trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (0.62 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
assert '*ROI:* All trades' in msg_mock.call_args_list[-1][0][0]
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (6.2 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
assert ('∙ `0.00006217 BTC (6.20%) (0.62 \N{GREEK CAPITAL LETTER SIGMA}%)`'
|
||||
in msg_mock.call_args_list[-1][0][0])
|
||||
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]
|
||||
|
||||
|
@ -172,7 +172,7 @@ def test_download_data_options() -> None:
|
||||
def test_plot_dataframe_options() -> None:
|
||||
args = [
|
||||
'plot-dataframe',
|
||||
'-c', 'config_bittrex.json.example',
|
||||
'-c', 'config_examples/config_bittrex.example.json',
|
||||
'--indicators1', 'sma10', 'sma100',
|
||||
'--indicators2', 'macd', 'fastd', 'fastk',
|
||||
'--plot-limit', '30',
|
||||
|
@ -28,7 +28,7 @@ from tests.conftest import log_has, log_has_re, patched_configuration_load_confi
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def all_conf():
|
||||
config_file = Path(__file__).parents[1] / "config_full.json.example"
|
||||
config_file = Path(__file__).parents[1] / "config_examples/config_full.example.json"
|
||||
conf = load_config_file(str(config_file))
|
||||
return conf
|
||||
|
||||
|
@ -67,12 +67,12 @@ def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config_bittrex.json.example']
|
||||
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
|
||||
|
||||
# Test Main + the KeyboardInterrupt exception
|
||||
with pytest.raises(SystemExit):
|
||||
main(args)
|
||||
assert log_has('Using config: config_bittrex.json.example ...', caplog)
|
||||
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
|
||||
assert log_has('Fatal exception!', caplog)
|
||||
|
||||
|
||||
@ -85,12 +85,12 @@ def test_main_keyboard_interrupt(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.wallets.Wallets.update', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config_bittrex.json.example']
|
||||
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
|
||||
|
||||
# Test Main + the KeyboardInterrupt exception
|
||||
with pytest.raises(SystemExit):
|
||||
main(args)
|
||||
assert log_has('Using config: config_bittrex.json.example ...', caplog)
|
||||
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
|
||||
assert log_has('SIGINT received, aborting ...', caplog)
|
||||
|
||||
|
||||
@ -106,12 +106,12 @@ def test_main_operational_exception(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = ['trade', '-c', 'config_bittrex.json.example']
|
||||
args = ['trade', '-c', 'config_examples/config_bittrex.example.json']
|
||||
|
||||
# Test Main + the KeyboardInterrupt exception
|
||||
with pytest.raises(SystemExit):
|
||||
main(args)
|
||||
assert log_has('Using config: config_bittrex.json.example ...', caplog)
|
||||
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
|
||||
assert log_has('Oh snap!', caplog)
|
||||
|
||||
|
||||
@ -157,12 +157,16 @@ def test_main_reload_config(mocker, default_conf, caplog) -> None:
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = Arguments(['trade', '-c', 'config_bittrex.json.example']).get_parsed_arg()
|
||||
args = Arguments([
|
||||
'trade',
|
||||
'-c',
|
||||
'config_examples/config_bittrex.example.json'
|
||||
]).get_parsed_arg()
|
||||
worker = Worker(args=args, config=default_conf)
|
||||
with pytest.raises(SystemExit):
|
||||
main(['trade', '-c', 'config_bittrex.json.example'])
|
||||
main(['trade', '-c', 'config_examples/config_bittrex.example.json'])
|
||||
|
||||
assert log_has('Using config: config_bittrex.json.example ...', caplog)
|
||||
assert log_has('Using config: config_examples/config_bittrex.example.json ...', caplog)
|
||||
assert worker_mock.call_count == 4
|
||||
assert reconfigure_mock.call_count == 1
|
||||
assert isinstance(worker.freqtrade, FreqtradeBot)
|
||||
@ -180,7 +184,11 @@ def test_reconfigure(mocker, default_conf) -> None:
|
||||
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
|
||||
mocker.patch('freqtrade.freqtradebot.init_db', MagicMock())
|
||||
|
||||
args = Arguments(['trade', '-c', 'config_bittrex.json.example']).get_parsed_arg()
|
||||
args = Arguments([
|
||||
'trade',
|
||||
'-c',
|
||||
'config_examples/config_bittrex.example.json'
|
||||
]).get_parsed_arg()
|
||||
worker = Worker(args=args, config=default_conf)
|
||||
freqtrade = worker.freqtrade
|
||||
|
||||
|
@ -364,7 +364,7 @@ def test_start_plot_dataframe(mocker):
|
||||
aup = mocker.patch("freqtrade.plot.plotting.load_and_plot_trades", MagicMock())
|
||||
args = [
|
||||
"plot-dataframe",
|
||||
"--config", "config_bittrex.json.example",
|
||||
"--config", "config_examples/config_bittrex.example.json",
|
||||
"--pairs", "ETH/BTC"
|
||||
]
|
||||
start_plot_dataframe(get_args(args))
|
||||
@ -408,7 +408,7 @@ def test_start_plot_profit(mocker):
|
||||
aup = mocker.patch("freqtrade.plot.plotting.plot_profit", MagicMock())
|
||||
args = [
|
||||
"plot-profit",
|
||||
"--config", "config_bittrex.json.example",
|
||||
"--config", "config_examples/config_bittrex.example.json",
|
||||
"--pairs", "ETH/BTC"
|
||||
]
|
||||
start_plot_profit(get_args(args))
|
||||
|
@ -197,3 +197,30 @@ def test__validate_stake_amount(mocker, default_conf,
|
||||
return_value=max_stake_amount)
|
||||
res = freqtrade.wallets._validate_stake_amount('XRP/USDT', stake_amount, min_stake_amount)
|
||||
assert res == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize('available_capital,closed_profit,open_stakes,free,expected', [
|
||||
(None, 10, 100, 910, 1000),
|
||||
(None, 0, 0, 2500, 2500),
|
||||
(None, 500, 0, 2500, 2000),
|
||||
(None, 500, 0, 2500, 2000),
|
||||
(None, -70, 0, 1930, 2000),
|
||||
# Only available balance matters when it's set.
|
||||
(100, 0, 0, 0, 100),
|
||||
(1000, 0, 2, 5, 1000),
|
||||
(1235, 2250, 2, 5, 1235),
|
||||
(1235, -2250, 2, 5, 1235),
|
||||
])
|
||||
def test_get_starting_balance(mocker, default_conf, available_capital, closed_profit,
|
||||
open_stakes, free, expected):
|
||||
if available_capital:
|
||||
default_conf['available_capital'] = available_capital
|
||||
mocker.patch("freqtrade.persistence.models.Trade.get_total_closed_profit",
|
||||
return_value=closed_profit)
|
||||
mocker.patch("freqtrade.persistence.models.Trade.total_open_trades_stakes",
|
||||
return_value=open_stakes)
|
||||
mocker.patch("freqtrade.wallets.Wallets.get_free", return_value=free)
|
||||
|
||||
freqtrade = get_patched_freqtradebot(mocker, default_conf)
|
||||
|
||||
assert freqtrade.wallets.get_starting_balance() == expected
|
||||
|
Loading…
Reference in New Issue
Block a user