Merge branch 'develop' into margin-db

This commit is contained in:
Sam Germain 2021-07-16 18:43:33 -06:00
commit 661bec1b5f
26 changed files with 200 additions and 153 deletions

View File

@ -1,11 +1,20 @@
{ {
"name": "freqtrade Develop", "name": "freqtrade Develop",
"build": {
"dockerComposeFile": [ "dockerfile": "Dockerfile",
"docker-compose.yml" "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/", "workspaceFolder": "/freqtrade/",
@ -25,20 +34,6 @@
"ms-python.vscode-pylance", "ms-python.vscode-pylance",
"davidanson.vscode-markdownlint", "davidanson.vscode-markdownlint",
"ms-azuretools.vscode-docker", "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"
} }

View File

@ -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:

View File

@ -79,13 +79,13 @@ jobs:
- name: Backtesting - name: Backtesting
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
- name: Hyperopt - name: Hyperopt
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all
@ -172,13 +172,13 @@ jobs:
- name: Backtesting - name: Backtesting
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
- name: Hyperopt - name: Hyperopt
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all
@ -239,13 +239,13 @@ jobs:
- name: Backtesting - name: Backtesting
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
- name: Hyperopt - name: Hyperopt
run: | run: |
cp config_bittrex.json.example config.json cp config_examples/config_bittrex.example.json config.json
freqtrade create-userdir --userdir user_data freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily --print-all

5
.gitignore vendored
View File

@ -95,3 +95,8 @@ target/
#exceptions #exceptions
!*.gitkeep !*.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

View File

@ -26,12 +26,12 @@ jobs:
# - coveralls || true # - coveralls || true
name: pytest name: pytest
- script: - script:
- cp config_bittrex.json.example config.json - cp config_examples/config_bittrex.example.json config.json
- freqtrade create-userdir --userdir user_data - freqtrade create-userdir --userdir user_data
- freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy - freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
name: backtest name: backtest
- script: - script:
- cp config_bittrex.json.example config.json - cp config_examples/config_bittrex.example.json config.json
- freqtrade create-userdir --userdir user_data - freqtrade create-userdir --userdir user_data
- freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily - freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt SampleHyperOpt --hyperopt-loss SharpeHyperOptLossDaily
name: hyperopt name: hyperopt

View File

@ -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 docker tag freqtrade:$TAG_PLOT ${IMAGE_NAME}:$TAG_PLOT
# Run backtest # 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 if [ $? -ne 0 ]; then
echo "failed running backtest" echo "failed running backtest"

View File

@ -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. 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 ``` json
"ccxt_async_config": { "ccxt_async_config": {

View File

@ -245,10 +245,10 @@ current max
Return a summary of your profit/loss and performance. Return a summary of your profit/loss and performance.
> **ROI:** Close trades > **ROI:** Close trades
> ∙ `0.00485701 BTC (258.45%)` > ∙ `0.00485701 BTC (2.2%) (15.2 Σ%)`
> ∙ `62.968 USD` > ∙ `62.968 USD`
> **ROI:** All trades > **ROI:** All trades
> ∙ `0.00255280 BTC (143.43%)` > ∙ `0.00255280 BTC (1.5%) (6.43 Σ%)`
> ∙ `33.095 EUR` > ∙ `33.095 EUR`
> >
> **Total Trade Count:** `138` > **Total Trade Count:** `138`
@ -257,6 +257,10 @@ Return a summary of your profit/loss and performance.
> **Avg. Duration:** `2:33:45` > **Avg. Duration:** `2:33:45`
> **Best Performing:** `PAY/BTC: 50.23%` > **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> ### /forcesell <trade_id>
> **BITTREX:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)` > **BITTREX:** Selling BTC/LTC with limit `0.01650000 (profit: ~-4.07%, -0.00008168)`

View File

@ -67,12 +67,16 @@ class Profit(BaseModel):
profit_closed_ratio_mean: float profit_closed_ratio_mean: float
profit_closed_percent_sum: float profit_closed_percent_sum: float
profit_closed_ratio_sum: float profit_closed_ratio_sum: float
profit_closed_percent: float
profit_closed_ratio: float
profit_closed_fiat: float profit_closed_fiat: float
profit_all_coin: float profit_all_coin: float
profit_all_percent_mean: float profit_all_percent_mean: float
profit_all_ratio_mean: float profit_all_ratio_mean: float
profit_all_percent_sum: float profit_all_percent_sum: float
profit_all_ratio_sum: float profit_all_ratio_sum: float
profit_all_percent: float
profit_all_ratio: float
profit_all_fiat: float profit_all_fiat: float
trade_count: int trade_count: int
closed_trade_count: int closed_trade_count: int
@ -115,6 +119,7 @@ class ShowConfig(BaseModel):
dry_run: bool dry_run: bool
stake_currency: str stake_currency: str
stake_amount: Union[float, str] stake_amount: Union[float, str]
available_capital: Optional[float]
stake_currency_decimals: int stake_currency_decimals: int
max_open_trades: int max_open_trades: int
minimal_roi: Dict[str, Any] minimal_roi: Dict[str, Any]

View File

@ -106,6 +106,7 @@ class RPC:
'stake_currency': config['stake_currency'], 'stake_currency': config['stake_currency'],
'stake_currency_decimals': decimals_per_coin(config['stake_currency']), 'stake_currency_decimals': decimals_per_coin(config['stake_currency']),
'stake_amount': config['stake_amount'], 'stake_amount': config['stake_amount'],
'available_capital': config.get('available_capital'),
'max_open_trades': (config['max_open_trades'] 'max_open_trades': (config['max_open_trades']
if config['max_open_trades'] != float('inf') else -1), if config['max_open_trades'] != float('inf') else -1),
'minimal_roi': config['minimal_roi'].copy() if 'minimal_roi' in config else {}, '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_coin_sum = round(sum(profit_all_coin), 8)
profit_all_ratio_mean = float(mean(profit_all_ratio) if profit_all_ratio else 0.0) 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 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_fiat = self._fiat_converter.convert_amount(
profit_all_coin_sum, profit_all_coin_sum,
stake_currency, stake_currency,
@ -412,12 +418,16 @@ class RPC:
'profit_closed_ratio_mean': profit_closed_ratio_mean, 'profit_closed_ratio_mean': profit_closed_ratio_mean,
'profit_closed_percent_sum': round(profit_closed_ratio_sum * 100, 2), 'profit_closed_percent_sum': round(profit_closed_ratio_sum * 100, 2),
'profit_closed_ratio_sum': profit_closed_ratio_sum, '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_closed_fiat': profit_closed_fiat,
'profit_all_coin': profit_all_coin_sum, 'profit_all_coin': profit_all_coin_sum,
'profit_all_percent_mean': round(profit_all_ratio_mean * 100, 2), 'profit_all_percent_mean': round(profit_all_ratio_mean * 100, 2),
'profit_all_ratio_mean': profit_all_ratio_mean, 'profit_all_ratio_mean': profit_all_ratio_mean,
'profit_all_percent_sum': round(profit_all_ratio_sum * 100, 2), 'profit_all_percent_sum': round(profit_all_ratio_sum * 100, 2),
'profit_all_ratio_sum': profit_all_ratio_sum, '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, 'profit_all_fiat': profit_all_fiat,
'trade_count': len(trades), 'trade_count': len(trades),
'closed_trade_count': len([t for t in trades if not t.is_open]), 'closed_trade_count': len([t for t in trades if not t.is_open]),

View File

@ -494,11 +494,11 @@ class Telegram(RPCHandler):
start_date) start_date)
profit_closed_coin = stats['profit_closed_coin'] profit_closed_coin = stats['profit_closed_coin']
profit_closed_percent_mean = stats['profit_closed_percent_mean'] 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_closed_fiat = stats['profit_closed_fiat']
profit_all_coin = stats['profit_all_coin'] profit_all_coin = stats['profit_all_coin']
profit_all_percent_mean = stats['profit_all_percent_mean'] 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'] profit_all_fiat = stats['profit_all_fiat']
trade_count = stats['trade_count'] trade_count = stats['trade_count']
first_trade_date = stats['first_trade_date'] first_trade_date = stats['first_trade_date']
@ -514,7 +514,7 @@ class Telegram(RPCHandler):
markdown_msg = ("*ROI:* Closed trades\n" markdown_msg = ("*ROI:* Closed trades\n"
f"∙ `{round_coin_value(profit_closed_coin, stake_cur)} " f"∙ `{round_coin_value(profit_closed_coin, stake_cur)} "
f"({profit_closed_percent_mean:.2f}%) " 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") f"∙ `{round_coin_value(profit_closed_fiat, fiat_disp_cur)}`\n")
else: else:
markdown_msg = "`No closed trade` \n" markdown_msg = "`No closed trade` \n"
@ -523,7 +523,7 @@ class Telegram(RPCHandler):
f"*ROI:* All trades\n" f"*ROI:* All trades\n"
f"∙ `{round_coin_value(profit_all_coin, stake_cur)} " f"∙ `{round_coin_value(profit_all_coin, stake_cur)} "
f"({profit_all_percent_mean:.2f}%) " 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"∙ `{round_coin_value(profit_all_fiat, fiat_disp_cur)}`\n"
f"*Total Trade Count:* `{trade_count}`\n" f"*Total Trade Count:* `{trade_count}`\n"
f"*{'First Trade opened' if not timescale else 'Showing Profit since'}:* " f"*{'First Trade opened' if not timescale else 'Showing Profit since'}:* "

View File

@ -129,6 +129,19 @@ class Wallets:
def get_all_balances(self) -> Dict[str, Any]: def get_all_balances(self) -> Dict[str, Any]:
return self._wallets 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): def get_total_stake_amount(self):
""" """
Return the total currently available balance in stake currency, including tied up stake and 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() max_stake_amount = self.get_available_stake_amount()
if min_stake_amount > max_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 return 0
if min_stake_amount is not None and stake_amount < min_stake_amount: if min_stake_amount is not None and stake_amount < min_stake_amount:
stake_amount = min_stake_amount stake_amount = min_stake_amount
logger.info( if self._log:
f"Stake amount for pair {pair} is too small ({stake_amount} < {min_stake_amount}), " logger.info(
f"adjusting to {min_stake_amount}." 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: if stake_amount > max_stake_amount:
stake_amount = max_stake_amount stake_amount = max_stake_amount
logger.info( if self._log:
f"Stake amount for pair {pair} is too big ({stake_amount} > {max_stake_amount}), " logger.info(
f"adjusting to {max_stake_amount}." f"Stake amount for pair {pair} is too big "
) f"({stake_amount} > {max_stake_amount}), adjusting to {max_stake_amount}."
)
return stake_amount return stake_amount

View File

@ -17,35 +17,20 @@ function check_installed_python() {
exit 2 exit 2
fi fi
which python3.8 for v in 8 9 7
if [ $? -eq 0 ]; then do
echo "using Python 3.8" PYTHON="python3.${v}"
PYTHON=python3.8 which $PYTHON
check_installed_pip if [ $? -eq 0 ]; then
return echo "using ${PYTHON}"
fi
which python3.9 check_installed_pip
if [ $? -eq 0 ]; then return
echo "using Python 3.9" fi
PYTHON=python3.9 done
check_installed_pip
return
fi
which python3.7 echo "No usable python found. Please make sure to have python3.7 or newer installed"
if [ $? -eq 0 ]; then exit 1
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
} }
function updateenv() { function updateenv() {
@ -122,6 +107,25 @@ function install_talib() {
cd .. 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 # Install bot MacOS
function install_macos() { function install_macos() {
if [ ! -x "$(command -v brew)" ] if [ ! -x "$(command -v brew)" ]
@ -131,8 +135,13 @@ function install_macos() {
echo "-------------------------" echo "-------------------------"
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
fi 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 install_talib
test_and_fix_python_on_mac
} }
# Install bot Debian_ubuntu # Install bot Debian_ubuntu
@ -189,19 +198,6 @@ function reset() {
updateenv 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() { function config() {
echo "-------------------------" echo "-------------------------"

View File

@ -26,7 +26,7 @@ from tests.conftest_trades import MOCK_TRADE_COUNT
def test_setup_utils_configuration(): def test_setup_utils_configuration():
args = [ 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) 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()) exitmock = mocker.patch("freqtrade.worker.Worker.exit", MagicMock())
args = [ args = [
'trade', 'trade',
'-c', 'config_bittrex.json.example' '-c', 'config_examples/config_bittrex.example.json'
] ]
start_trading(get_args(args)) start_trading(get_args(args))
assert exitmock.call_count == 1 assert exitmock.call_count == 1
@ -127,10 +127,10 @@ def test_list_timeframes(mocker, capsys):
match=r"This command requires a configured exchange.*"): match=r"This command requires a configured exchange.*"):
start_list_timeframes(pargs) start_list_timeframes(pargs)
# Test with --config config_bittrex.json.example # Test with --config config_examples/config_bittrex.example.json
args = [ args = [
"list-timeframes", "list-timeframes",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
] ]
start_list_timeframes(get_args(args)) start_list_timeframes(get_args(args))
captured = capsys.readouterr() captured = capsys.readouterr()
@ -174,7 +174,7 @@ def test_list_timeframes(mocker, capsys):
# Test with --one-column # Test with --one-column
args = [ args = [
"list-timeframes", "list-timeframes",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--one-column", "--one-column",
] ]
start_list_timeframes(get_args(args)) 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.*"): match=r"This command requires a configured exchange.*"):
start_list_markets(pargs, False) start_list_markets(pargs, False)
# Test with --config config_bittrex.json.example # Test with --config config_examples/config_bittrex.example.json
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-list", "--print-list",
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -244,7 +244,7 @@ def test_list_markets(mocker, markets, capsys):
# Test with --all: all markets # Test with --all: all markets
args = [ args = [
"list-markets", "--all", "list-markets", "--all",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-list", "--print-list",
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -257,7 +257,7 @@ def test_list_markets(mocker, markets, capsys):
# Test list-pairs subcommand: active pairs # Test list-pairs subcommand: active pairs
args = [ args = [
"list-pairs", "list-pairs",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-list", "--print-list",
] ]
start_list_markets(get_args(args), True) 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 # Test list-pairs subcommand with --all: all pairs
args = [ args = [
"list-pairs", "--all", "list-pairs", "--all",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-list", "--print-list",
] ]
start_list_markets(get_args(args), True) start_list_markets(get_args(args), True)
@ -282,7 +282,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, base=ETH, LTC # active markets, base=ETH, LTC
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "ETH", "LTC", "--base", "ETH", "LTC",
"--print-list", "--print-list",
] ]
@ -295,7 +295,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, base=LTC # active markets, base=LTC
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--base", "LTC",
"--print-list", "--print-list",
] ]
@ -308,7 +308,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, quote=USDT, USD # active markets, quote=USDT, USD
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--quote", "USDT", "USD", "--quote", "USDT", "USD",
"--print-list", "--print-list",
] ]
@ -321,7 +321,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, quote=USDT # active markets, quote=USDT
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--quote", "USDT", "--quote", "USDT",
"--print-list", "--print-list",
] ]
@ -334,7 +334,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, base=LTC, quote=USDT # active markets, base=LTC, quote=USDT
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--quote", "USDT", "--base", "LTC", "--quote", "USDT",
"--print-list", "--print-list",
] ]
@ -347,7 +347,7 @@ def test_list_markets(mocker, markets, capsys):
# active pairs, base=LTC, quote=USDT # active pairs, base=LTC, quote=USDT
args = [ args = [
"list-pairs", "list-pairs",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--quote", "USD", "--base", "LTC", "--quote", "USD",
"--print-list", "--print-list",
] ]
@ -360,7 +360,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, base=LTC, quote=USDT, NONEXISTENT # active markets, base=LTC, quote=USDT, NONEXISTENT
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--quote", "USDT", "NONEXISTENT", "--base", "LTC", "--quote", "USDT", "NONEXISTENT",
"--print-list", "--print-list",
] ]
@ -373,7 +373,7 @@ def test_list_markets(mocker, markets, capsys):
# active markets, base=LTC, quote=NONEXISTENT # active markets, base=LTC, quote=NONEXISTENT
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--quote", "NONEXISTENT", "--base", "LTC", "--quote", "NONEXISTENT",
"--print-list", "--print-list",
] ]
@ -386,7 +386,7 @@ def test_list_markets(mocker, markets, capsys):
# Test tabular output # Test tabular output
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
captured = capsys.readouterr() captured = capsys.readouterr()
@ -396,7 +396,7 @@ def test_list_markets(mocker, markets, capsys):
# Test tabular output, no markets found # Test tabular output, no markets found
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--base", "LTC", "--quote", "NONEXISTENT", "--base", "LTC", "--quote", "NONEXISTENT",
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -408,7 +408,7 @@ def test_list_markets(mocker, markets, capsys):
# Test --print-json # Test --print-json
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-json" "--print-json"
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -420,7 +420,7 @@ def test_list_markets(mocker, markets, capsys):
# Test --print-csv # Test --print-csv
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--print-csv" "--print-csv"
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -432,7 +432,7 @@ def test_list_markets(mocker, markets, capsys):
# Test --one-column # Test --one-column
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--one-column" "--one-column"
] ]
start_list_markets(get_args(args), False) start_list_markets(get_args(args), False)
@ -444,7 +444,7 @@ def test_list_markets(mocker, markets, capsys):
# Test --one-column # Test --one-column
args = [ args = [
"list-markets", "list-markets",
'--config', 'config_bittrex.json.example', '--config', 'config_examples/config_bittrex.example.json',
"--one-column" "--one-column"
] ]
with pytest.raises(OperationalException, match=r"Cannot get markets.*"): 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) patched_configuration_load_config_file(mocker, default_conf)
args = [ args = [
'test-pairlist', 'test-pairlist',
'-c', 'config_bittrex.json.example' '-c', 'config_examples/config_bittrex.example.json'
] ]
start_test_pairlist(get_args(args)) start_test_pairlist(get_args(args))
@ -901,7 +901,7 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
args = [ args = [
'test-pairlist', 'test-pairlist',
'-c', 'config_bittrex.json.example', '-c', 'config_examples/config_bittrex.example.json',
'--one-column', '--one-column',
] ]
start_test_pairlist(get_args(args)) start_test_pairlist(get_args(args))
@ -910,7 +910,7 @@ def test_start_test_pairlist(mocker, caplog, tickers, default_conf, capsys):
args = [ args = [
'test-pairlist', 'test-pairlist',
'-c', 'config_bittrex.json.example', '-c', 'config_examples/config_bittrex.example.json',
'--print-json', '--print-json',
] ]
start_test_pairlist(get_args(args)) start_test_pairlist(get_args(args))

View File

@ -677,12 +677,16 @@ def test_api_profit(botclient, mocker, ticker, fee, markets):
'profit_all_ratio_mean': -0.6641100666666667, 'profit_all_ratio_mean': -0.6641100666666667,
'profit_all_percent_sum': -398.47, 'profit_all_percent_sum': -398.47,
'profit_all_ratio_sum': -3.9846604, 'profit_all_ratio_sum': -3.9846604,
'profit_all_percent': -4.41,
'profit_all_ratio': -0.044063014216106644,
'profit_closed_coin': 0.00073913, 'profit_closed_coin': 0.00073913,
'profit_closed_fiat': 9.124559849999999, 'profit_closed_fiat': 9.124559849999999,
'profit_closed_ratio_mean': 0.0075, 'profit_closed_ratio_mean': 0.0075,
'profit_closed_percent_mean': 0.75, 'profit_closed_percent_mean': 0.75,
'profit_closed_ratio_sum': 0.015, 'profit_closed_ratio_sum': 0.015,
'profit_closed_percent_sum': 1.5, 'profit_closed_percent_sum': 1.5,
'profit_closed_ratio': 7.391275897987988e-07,
'profit_closed_percent': 0.0,
'trade_count': 6, 'trade_count': 6,
'closed_trade_count': 2, 'closed_trade_count': 2,
'winning_trades': 2, 'winning_trades': 2,

View File

@ -452,7 +452,8 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up, fee,
assert msg_mock.call_count == 1 assert msg_mock.call_count == 1
assert 'No closed trade' in msg_mock.call_args_list[-1][0][0] 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 '*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]) in msg_mock.call_args_list[-1][0][0])
msg_mock.reset_mock() 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()) telegram._profit(update=update, context=MagicMock())
assert msg_mock.call_count == 1 assert msg_mock.call_count == 1
assert '*ROI:* Closed trades' in msg_mock.call_args_list[-1][0][0] 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]) in msg_mock.call_args_list[-1][0][0])
assert '∙ `0.933 USD`' 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 '*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]) in msg_mock.call_args_list[-1][0][0])
assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0] assert '∙ `0.933 USD`' in msg_mock.call_args_list[-1][0][0]

View File

@ -172,7 +172,7 @@ def test_download_data_options() -> None:
def test_plot_dataframe_options() -> None: def test_plot_dataframe_options() -> None:
args = [ args = [
'plot-dataframe', 'plot-dataframe',
'-c', 'config_bittrex.json.example', '-c', 'config_examples/config_bittrex.example.json',
'--indicators1', 'sma10', 'sma100', '--indicators1', 'sma10', 'sma100',
'--indicators2', 'macd', 'fastd', 'fastk', '--indicators2', 'macd', 'fastd', 'fastk',
'--plot-limit', '30', '--plot-limit', '30',

View File

@ -28,7 +28,7 @@ from tests.conftest import log_has, log_has_re, patched_configuration_load_confi
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def all_conf(): 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)) conf = load_config_file(str(config_file))
return conf return conf

View File

@ -67,12 +67,12 @@ def test_main_fatal_exception(mocker, default_conf, caplog) -> None:
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock()) mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.init_db', 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 # Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
main(args) 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) 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.wallets.Wallets.update', MagicMock())
mocker.patch('freqtrade.freqtradebot.init_db', 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 # Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
main(args) 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) 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.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.init_db', 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 # Test Main + the KeyboardInterrupt exception
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
main(args) 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) 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.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.init_db', 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) worker = Worker(args=args, config=default_conf)
with pytest.raises(SystemExit): 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 worker_mock.call_count == 4
assert reconfigure_mock.call_count == 1 assert reconfigure_mock.call_count == 1
assert isinstance(worker.freqtrade, FreqtradeBot) 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.RPCManager', MagicMock())
mocker.patch('freqtrade.freqtradebot.init_db', 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) worker = Worker(args=args, config=default_conf)
freqtrade = worker.freqtrade freqtrade = worker.freqtrade

View File

@ -364,7 +364,7 @@ def test_start_plot_dataframe(mocker):
aup = mocker.patch("freqtrade.plot.plotting.load_and_plot_trades", MagicMock()) aup = mocker.patch("freqtrade.plot.plotting.load_and_plot_trades", MagicMock())
args = [ args = [
"plot-dataframe", "plot-dataframe",
"--config", "config_bittrex.json.example", "--config", "config_examples/config_bittrex.example.json",
"--pairs", "ETH/BTC" "--pairs", "ETH/BTC"
] ]
start_plot_dataframe(get_args(args)) 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()) aup = mocker.patch("freqtrade.plot.plotting.plot_profit", MagicMock())
args = [ args = [
"plot-profit", "plot-profit",
"--config", "config_bittrex.json.example", "--config", "config_examples/config_bittrex.example.json",
"--pairs", "ETH/BTC" "--pairs", "ETH/BTC"
] ]
start_plot_profit(get_args(args)) start_plot_profit(get_args(args))

View File

@ -197,3 +197,30 @@ def test__validate_stake_amount(mocker, default_conf,
return_value=max_stake_amount) return_value=max_stake_amount)
res = freqtrade.wallets._validate_stake_amount('XRP/USDT', stake_amount, min_stake_amount) res = freqtrade.wallets._validate_stake_amount('XRP/USDT', stake_amount, min_stake_amount)
assert res == expected 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