diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 912b906d7..a2f6567dc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -90,7 +90,7 @@ jobs:
- name: Backtesting (multi)
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade new-strategy -s AwesomeStrategy
freqtrade new-strategy -s AwesomeStrategyMin --template minimal
@@ -98,7 +98,7 @@ jobs:
- name: Hyperopt
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 6 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
@@ -200,14 +200,14 @@ jobs:
- name: Backtesting
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade new-strategy -s AwesomeStrategyAdv --template advanced
freqtrade backtesting --datadir tests/testdata --strategy AwesomeStrategyAdv
- name: Hyperopt
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
@@ -275,13 +275,13 @@ jobs:
- name: Backtesting
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade backtesting --datadir tests/testdata --strategy SampleStrategy
- name: Hyperopt
run: |
- cp config_examples/config_bittrex.example.json config.json
+ cp tests/testdata/config.tests.json config.json
freqtrade create-userdir --userdir user_data
freqtrade hyperopt --datadir tests/testdata -e 5 --strategy SampleStrategy --hyperopt-loss SharpeHyperOptLossDaily --print-all
diff --git a/Dockerfile b/Dockerfile
index e2adf65f9..38f9ca788 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM python:3.11.6-slim-bullseye as base
+FROM python:3.11.6-slim-bookworm as base
# Setup env
ENV LANG C.UTF-8
diff --git a/README.md b/README.md
index 0cacfe703..4ed144f93 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,6 @@ hesitate to read the source code and understand the mechanism of this bot.
Please read the [exchange specific notes](docs/exchanges.md) to learn about eventual, special configurations needed for each exchange.
- [X] [Binance](https://www.binance.com/)
-- [X] [Bittrex](https://bittrex.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)
- [X] [Huobi](http://huobi.com/)
- [X] [Kraken](https://kraken.com/)
diff --git a/build_helpers/publish_docker_arm64.sh b/build_helpers/publish_docker_arm64.sh
index 8f0de2cc9..71fc01509 100755
--- a/build_helpers/publish_docker_arm64.sh
+++ b/build_helpers/publish_docker_arm64.sh
@@ -54,7 +54,7 @@ docker tag freqtrade:$TAG_FREQAI_ARM ${CACHE_IMAGE}:$TAG_FREQAI_ARM
docker tag freqtrade:$TAG_FREQAI_RL_ARM ${CACHE_IMAGE}:$TAG_FREQAI_RL_ARM
# Run backtest
-docker run --rm -v $(pwd)/config_examples/config_bittrex.example.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
+docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG_ARM} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
if [ $? -ne 0 ]; then
echo "failed running backtest"
diff --git a/build_helpers/publish_docker_multi.sh b/build_helpers/publish_docker_multi.sh
index 72b20ac5d..34dc1faa3 100755
--- a/build_helpers/publish_docker_multi.sh
+++ b/build_helpers/publish_docker_multi.sh
@@ -67,7 +67,7 @@ docker tag freqtrade:$TAG_FREQAI ${CACHE_IMAGE}:$TAG_FREQAI
docker tag freqtrade:$TAG_FREQAI_RL ${CACHE_IMAGE}:$TAG_FREQAI_RL
# Run backtest
-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 StrategyTestV3
+docker run --rm -v $(pwd)/tests/testdata/config.tests.json:/freqtrade/config.json:ro -v $(pwd)/tests:/tests freqtrade:${TAG} backtesting --datadir /tests/testdata --strategy-path /tests/strategy/strats/ --strategy StrategyTestV3
if [ $? -ne 0 ]; then
echo "failed running backtest"
diff --git a/config_examples/config_binance.example.json b/config_examples/config_binance.example.json
index 7968bdedc..3a2cea530 100644
--- a/config_examples/config_binance.example.json
+++ b/config_examples/config_binance.example.json
@@ -1,6 +1,6 @@
{
"max_open_trades": 3,
- "stake_currency": "BTC",
+ "stake_currency": "USDT",
"stake_amount": 0.05,
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "USD",
@@ -36,21 +36,21 @@
"ccxt_async_config": {
},
"pair_whitelist": [
- "ALGO/BTC",
- "ATOM/BTC",
- "BAT/BTC",
- "BCH/BTC",
- "BRD/BTC",
- "EOS/BTC",
- "ETH/BTC",
- "IOTA/BTC",
- "LINK/BTC",
- "LTC/BTC",
- "NEO/BTC",
- "NXS/BTC",
- "XMR/BTC",
- "XRP/BTC",
- "XTZ/BTC"
+ "ALGO/USDT",
+ "ATOM/USDT",
+ "BAT/USDT",
+ "BCH/USDT",
+ "BRD/USDT",
+ "EOS/USDT",
+ "ETH/USDT",
+ "IOTA/USDT",
+ "LINK/USDT",
+ "LTC/USDT",
+ "NEO/USDT",
+ "NXS/USDT",
+ "XMR/USDT",
+ "XRP/USDT",
+ "XTZ/USDT"
],
"pair_blacklist": [
"BNB/.*"
diff --git a/docker/Dockerfile.armhf b/docker/Dockerfile.armhf
index c17c0adbe..c8efa4232 100644
--- a/docker/Dockerfile.armhf
+++ b/docker/Dockerfile.armhf
@@ -1,4 +1,4 @@
-FROM python:3.9.16-slim-bullseye as base
+FROM python:3.11.6-slim-bookworm as base
# Setup env
ENV LANG C.UTF-8
@@ -11,7 +11,7 @@ ENV FT_APP_ENV="docker"
# Prepare environment
RUN mkdir /freqtrade \
&& apt-get update \
- && apt-get -y install sudo libatlas3-base libopenblas-base curl sqlite3 libhdf5-dev libutf8proc-dev libsnappy-dev \
+ && apt-get -y install sudo libatlas3-base libopenblas-dev curl sqlite3 libhdf5-dev libutf8proc-dev libsnappy-dev \
&& apt-get clean \
&& useradd -u 1000 -G sudo -U -m ftuser \
&& chown ftuser:ftuser /freqtrade \
@@ -24,7 +24,7 @@ WORKDIR /freqtrade
# Install dependencies
FROM base as python-deps
RUN apt-get update \
- && apt-get -y install build-essential libssl-dev libffi-dev libopenblas-dev libgfortran5 pkg-config cmake gcc \
+ && apt-get -y install build-essential libssl-dev libffi-dev libgfortran5 pkg-config cmake gcc \
&& apt-get clean \
&& echo "[global]\nextra-index-url=https://www.piwheels.org/simple" > /etc/pip.conf
diff --git a/docs/backtesting.md b/docs/backtesting.md
index 41498fb00..d13b00a38 100644
--- a/docs/backtesting.md
+++ b/docs/backtesting.md
@@ -170,11 +170,11 @@ freqtrade backtesting --strategy AwesomeStrategy --dry-run-wallet 1000
Using a different on-disk historical candle (OHLCV) data source
-Assume you downloaded the history data from the Bittrex exchange and kept it in the `user_data/data/bittrex-20180101` directory.
+Assume you downloaded the history data from the Binance exchange and kept it in the `user_data/data/binance-20180101` directory.
You can then use this data for backtesting as follows:
```bash
-freqtrade backtesting --strategy AwesomeStrategy --datadir user_data/data/bittrex-20180101
+freqtrade backtesting --strategy AwesomeStrategy --datadir user_data/data/binance-20180101
```
---
diff --git a/docs/configuration.md b/docs/configuration.md
index 7303f78c7..313e3e456 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -594,7 +594,7 @@ creating trades on the exchange.
```json
"exchange": {
- "name": "bittrex",
+ "name": "binance",
"key": "key",
"secret": "secret",
...
@@ -644,7 +644,7 @@ API Keys are usually only required for live trading (trading for real money, bot
```json
{
"exchange": {
- "name": "bittrex",
+ "name": "binance",
"key": "af8ddd35195e9dc500b9a6f799f6f5c93d89193b",
"secret": "08a9dc6db3d7b53e1acebd9275677f4b0a04f1a5",
//"password": "", // Optional, not needed by all exchanges)
diff --git a/docs/freqai-parameter-table.md b/docs/freqai-parameter-table.md
index 95687c7ab..905ea479a 100644
--- a/docs/freqai-parameter-table.md
+++ b/docs/freqai-parameter-table.md
@@ -74,7 +74,6 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
| | **Reinforcement Learning Parameters within the `freqai.rl_config` sub dictionary**
| `rl_config` | A dictionary containing the control parameters for a Reinforcement Learning model.
**Datatype:** Dictionary.
| `train_cycles` | Training time steps will be set based on the `train_cycles * number of training data points.
**Datatype:** Integer.
-| `cpu_count` | Number of processors to dedicate to the Reinforcement Learning training process.
**Datatype:** int.
| `max_trade_duration_candles`| Guides the agent training to keep trades below desired length. Example usage shown in `prediction_models/ReinforcementLearner.py` within the customizable `calculate_reward()` function.
**Datatype:** int.
| `model_type` | Model string from stable_baselines3 or SBcontrib. Available strings include: `'TRPO', 'ARS', 'RecurrentPPO', 'MaskablePPO', 'PPO', 'A2C', 'DQN'`. User should ensure that `model_training_parameters` match those available to the corresponding stable_baselines3 model by visiting their documentaiton. [PPO doc](https://stable-baselines3.readthedocs.io/en/master/modules/ppo.html) (external website)
**Datatype:** string.
| `policy_type` | One of the available policy types from stable_baselines3
**Datatype:** string.
diff --git a/docs/index.md b/docs/index.md
index 190e7e3c3..dd80db958 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -40,7 +40,6 @@ Freqtrade is a free and open source crypto trading bot written in Python. It is
Please read the [exchange specific notes](exchanges.md) to learn about eventual, special configurations needed for each exchange.
- [X] [Binance](https://www.binance.com/)
-- [X] [Bittrex](https://bittrex.com/)
- [X] [Gate.io](https://www.gate.io/ref/6266643)
- [X] [Huobi](http://huobi.com/)
- [X] [Kraken](https://kraken.com/)
diff --git a/docs/requirements-docs.txt b/docs/requirements-docs.txt
index 8269c02da..31e04a74f 100644
--- a/docs/requirements-docs.txt
+++ b/docs/requirements-docs.txt
@@ -1,6 +1,6 @@
markdown==3.5.1
mkdocs==1.5.3
-mkdocs-material==9.4.8
+mkdocs-material==9.4.10
mdx_truly_sane_lists==1.3
pymdown-extensions==10.4
jinja2==3.1.2
diff --git a/docs/utils.md b/docs/utils.md
index 65ab50b9e..ac0d341bd 100644
--- a/docs/utils.md
+++ b/docs/utils.md
@@ -427,25 +427,33 @@ zb True missing opt: fetchMyTrades
Use the `list-timeframes` subcommand to see the list of timeframes available for the exchange.
```
-usage: freqtrade list-timeframes [-h] [-v] [--logfile FILE] [-V] [-c PATH] [-d PATH] [--userdir PATH] [--exchange EXCHANGE] [-1]
+usage: freqtrade list-timeframes [-h] [-v] [--logfile FILE] [-V] [-c PATH]
+ [-d PATH] [--userdir PATH]
+ [--exchange EXCHANGE] [-1]
-optional arguments:
+options:
-h, --help show this help message and exit
- --exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no config is provided.
+ --exchange EXCHANGE Exchange name. Only valid if no config is provided.
-1, --one-column Print output in one column.
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
- --logfile FILE Log to the file specified. Special values are: 'syslog', 'journald'. See the documentation for more details.
+ --logfile FILE, --log-file FILE
+ Log to the file specified. Special values are:
+ 'syslog', 'journald'. See the documentation for more
+ details.
-V, --version show program's version number and exit
-c PATH, --config PATH
- Specify configuration file (default: `config.json`). Multiple --config options may be used. Can be set to `-`
- to read config from stdin.
- -d PATH, --datadir PATH
+ Specify configuration file (default:
+ `userdir/config.json` or `config.json` whichever
+ exists). Multiple --config options may be used. Can be
+ set to `-` to read config from stdin.
+ -d PATH, --datadir PATH, --data-dir PATH
Path to directory with historical backtesting data.
--userdir PATH, --user-data-dir PATH
Path to userdata directory.
+
```
* Example: see the timeframes for the 'binance' exchange, set in the configuration file:
@@ -479,20 +487,17 @@ usage: freqtrade list-markets [-h] [-v] [--logfile FILE] [-V] [-c PATH]
[-d PATH] [--userdir PATH] [--exchange EXCHANGE]
[--print-list] [--print-json] [-1] [--print-csv]
[--base BASE_CURRENCY [BASE_CURRENCY ...]]
- [--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]] [-a]
- [--trading-mode {spot,margin,futures}]
-
+ [--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]]
+ [-a] [--trading-mode {spot,margin,futures}]
usage: freqtrade list-pairs [-h] [-v] [--logfile FILE] [-V] [-c PATH]
[-d PATH] [--userdir PATH] [--exchange EXCHANGE]
[--print-list] [--print-json] [-1] [--print-csv]
[--base BASE_CURRENCY [BASE_CURRENCY ...]]
[--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]] [-a]
[--trading-mode {spot,margin,futures}]
-
-optional arguments:
+options:
-h, --help show this help message and exit
- --exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
- config is provided.
+ --exchange EXCHANGE Exchange name. Only valid if no config is provided.
--print-list Print list of pairs or market symbols. By default data
is printed in the tabular format.
--print-json Print list of pairs or market symbols in JSON format.
@@ -504,20 +509,22 @@ optional arguments:
Specify quote currency(-ies). Space-separated list.
-a, --all Print all pairs or market symbols. By default only
active ones are shown.
- --trading-mode {spot,margin,futures}
+ --trading-mode {spot,margin,futures}, --tradingmode {spot,margin,futures}
Select Trading mode
Common arguments:
-v, --verbose Verbose mode (-vv for more, -vvv to get all messages).
- --logfile FILE Log to the file specified. Special values are:
+ --logfile FILE, --log-file FILE
+ Log to the file specified. Special values are:
'syslog', 'journald'. See the documentation for more
details.
-V, --version show program's version number and exit
-c PATH, --config PATH
- Specify configuration file (default: `config.json`).
- Multiple --config options may be used. Can be set to
- `-` to read config from stdin.
- -d PATH, --datadir PATH
+ Specify configuration file (default:
+ `userdir/config.json` or `config.json` whichever
+ exists). Multiple --config options may be used. Can be
+ set to `-` to read config from stdin.
+ -d PATH, --datadir PATH, --data-dir PATH
Path to directory with historical backtesting data.
--userdir PATH, --user-data-dir PATH
Path to userdata directory.
@@ -532,7 +539,7 @@ Pairs/markets are sorted by its symbol string in the printed output.
### Examples
* Print the list of active pairs with quote currency USD on exchange, specified in the default
-configuration file (i.e. pairs on the "Bittrex" exchange) in JSON format:
+configuration file (i.e. pairs on the "Binance" exchange) in JSON format:
```
$ freqtrade list-pairs --quote USD --print-json
@@ -564,7 +571,7 @@ usage: freqtrade test-pairlist [-h] [--userdir PATH] [-v] [-c PATH]
[--quote QUOTE_CURRENCY [QUOTE_CURRENCY ...]]
[-1] [--print-json] [--exchange EXCHANGE]
-optional arguments:
+options:
-h, --help show this help message and exit
--userdir PATH, --user-data-dir PATH
Path to userdata directory.
@@ -578,8 +585,7 @@ optional arguments:
Specify quote currency(-ies). Space-separated list.
-1, --one-column Print output in one column.
--print-json Print list of pairs or market symbols in JSON format.
- --exchange EXCHANGE Exchange name (default: `bittrex`). Only valid if no
- config is provided.
+ --exchange EXCHANGE Exchange name. Only valid if no config is provided.
```
diff --git a/freqtrade/commands/build_config_commands.py b/freqtrade/commands/build_config_commands.py
index 6692ad59a..2dff87a7d 100644
--- a/freqtrade/commands/build_config_commands.py
+++ b/freqtrade/commands/build_config_commands.py
@@ -108,7 +108,6 @@ def ask_user_config() -> Dict[str, Any]:
"choices": [
"binance",
"binanceus",
- "bittrex",
"gate",
"huobi",
"kraken",
diff --git a/freqtrade/exchange/common.py b/freqtrade/exchange/common.py
index 10dfdf178..36bed9b20 100644
--- a/freqtrade/exchange/common.py
+++ b/freqtrade/exchange/common.py
@@ -52,7 +52,6 @@ MAP_EXCHANGE_CHILDCLASS = {
SUPPORTED_EXCHANGES = [
'binance',
- 'bittrex',
'gate',
'huobi',
'kraken',
diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py
index 603c161cf..5d0bc704f 100644
--- a/freqtrade/exchange/exchange.py
+++ b/freqtrade/exchange/exchange.py
@@ -486,11 +486,14 @@ class Exchange:
except ccxt.BaseError:
logger.exception('Unable to initialize markets.')
- def reload_markets(self) -> None:
+ def reload_markets(self, force: bool = False) -> None:
"""Reload markets both sync and async if refresh interval has passed """
# Check whether markets have to be reloaded
- if (self._last_markets_refresh > 0) and (
- self._last_markets_refresh + self.markets_refresh_interval > dt_ts()):
+ if (
+ not force
+ and self._last_markets_refresh > 0
+ and (self._last_markets_refresh + self.markets_refresh_interval > dt_ts())
+ ):
return None
logger.debug("Performing scheduled market reload..")
try:
@@ -1228,16 +1231,16 @@ class Exchange:
return order
except ccxt.InsufficientFunds as e:
raise InsufficientFundsError(
- f'Insufficient funds to create {ordertype} sell order on market {pair}. '
- f'Tried to sell amount {amount} at rate {limit_rate}. '
- f'Message: {e}') from e
- except ccxt.InvalidOrder as e:
+ f'Insufficient funds to create {ordertype} {side} order on market {pair}. '
+ f'Tried to {side} amount {amount} at rate {limit_rate} with '
+ f'stop-price {stop_price_norm}. Message: {e}') from e
+ except (ccxt.InvalidOrder, ccxt.BadRequest) as e:
# Errors:
# `Order would trigger immediately.`
raise InvalidOrderException(
- f'Could not create {ordertype} sell order on market {pair}. '
- f'Tried to sell amount {amount} at rate {limit_rate}. '
- f'Message: {e}') from e
+ f'Could not create {ordertype} {side} order on market {pair}. '
+ f'Tried to {side} amount {amount} at rate {limit_rate} with '
+ f'stop-price {stop_price_norm}. Message: {e}') from e
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
@@ -1496,8 +1499,9 @@ class Exchange:
@retrier
def fetch_bids_asks(self, symbols: Optional[List[str]] = None, cached: bool = False) -> Dict:
"""
+ :param symbols: List of symbols to fetch
:param cached: Allow cached result
- :return: fetch_tickers result
+ :return: fetch_bids_asks result
"""
if not self.exchange_has('fetchBidsAsks'):
return {}
@@ -1546,6 +1550,12 @@ class Exchange:
raise OperationalException(
f'Exchange {self._api.name} does not support fetching tickers in batch. '
f'Message: {e}') from e
+ except ccxt.BadSymbol as e:
+ logger.warning(f"Could not load tickers due to {e.__class__.__name__}. Message: {e} ."
+ "Reloading markets.")
+ self.reload_markets(True)
+ # Re-raise exception to repeat the call.
+ raise TemporaryError from e
except ccxt.DDoSProtection as e:
raise DDosProtection(e) from e
except (ccxt.NetworkError, ccxt.ExchangeError) as e:
diff --git a/freqtrade/freqai/tensorboard/TensorboardCallback.py b/freqtrade/freqai/tensorboard/TensorboardCallback.py
index 2be917616..b8a351498 100644
--- a/freqtrade/freqai/tensorboard/TensorboardCallback.py
+++ b/freqtrade/freqai/tensorboard/TensorboardCallback.py
@@ -3,7 +3,6 @@ from typing import Any, Dict, Type, Union
from stable_baselines3.common.callbacks import BaseCallback
from stable_baselines3.common.logger import HParam
-from stable_baselines3.common.vec_env import VecEnv
from freqtrade.freqai.RL.BaseEnvironment import BaseActions
@@ -13,13 +12,9 @@ class TensorboardCallback(BaseCallback):
Custom callback for plotting additional values in tensorboard and
episodic summary reports.
"""
- # Override training_env type to fix type errors
- training_env: Union[VecEnv, None] = None
-
def __init__(self, verbose=1, actions: Type[Enum] = BaseActions):
super().__init__(verbose)
self.model: Any = None
- self.logger: Any = None
self.actions: Type[Enum] = actions
def _on_training_start(self) -> None:
@@ -47,8 +42,6 @@ class TensorboardCallback(BaseCallback):
def _on_step(self) -> bool:
local_info = self.locals["infos"][0]
- if self.training_env is None:
- return True
if hasattr(self.training_env, 'envs'):
tensorboard_metrics = self.training_env.envs[0].unwrapped.tensorboard_metrics
diff --git a/freqtrade/optimize/hyperopt_auto.py b/freqtrade/optimize/hyperopt_auto.py
index 13c036a28..a3e2ef058 100644
--- a/freqtrade/optimize/hyperopt_auto.py
+++ b/freqtrade/optimize/hyperopt_auto.py
@@ -21,7 +21,7 @@ logger = logging.getLogger(__name__)
def _format_exception_message(space: str, ignore_missing_space: bool) -> None:
msg = (f"The '{space}' space is included into the hyperoptimization "
- f"but no parameter for this space was not found in your Strategy. "
+ f"but no parameter for this space was found in your Strategy. "
)
if ignore_missing_space:
logger.warning(msg + "This space will be ignored.")
diff --git a/freqtrade/persistence/trade_model.py b/freqtrade/persistence/trade_model.py
index 241ef70f5..3f721f1e8 100644
--- a/freqtrade/persistence/trade_model.py
+++ b/freqtrade/persistence/trade_model.py
@@ -1066,7 +1066,10 @@ class LocalTrade:
exit_amount = o.safe_amount_after_fee
prof = self.calculate_profit(exit_rate, exit_amount, float(avg_price))
close_profit_abs += prof.profit_abs
- close_profit = prof.profit_ratio
+ if total_stake > 0:
+ # This needs to be calculated based on the last occuring exit to be aligned
+ # with realized_profit.
+ close_profit = (close_profit_abs / total_stake) * self.leverage
else:
total_stake = total_stake + self._calc_open_trade_value(tmp_amount, price)
max_stake_amount += (tmp_amount * price)
diff --git a/freqtrade/plot/plotting.py b/freqtrade/plot/plotting.py
index 9ed7bbc46..e0aa2437a 100644
--- a/freqtrade/plot/plotting.py
+++ b/freqtrade/plot/plotting.py
@@ -21,6 +21,7 @@ from freqtrade.misc import pair_to_filename
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
from freqtrade.strategy import IStrategy
+from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
logger = logging.getLogger(__name__)
@@ -636,7 +637,7 @@ def load_and_plot_trades(config: Config):
exchange = ExchangeResolver.load_exchange(config)
IStrategy.dp = DataProvider(config, exchange)
strategy.ft_bot_start()
- strategy.bot_loop_start(datetime.now(timezone.utc))
+ strategy_safe_wrapper(strategy.bot_loop_start)(current_time=datetime.now(timezone.utc))
plot_elements = init_plotscript(config, list(exchange.markets), strategy.startup_candle_count)
timerange = plot_elements['timerange']
trades = plot_elements['trades']
diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py
index e64570b9e..8be1f0336 100644
--- a/freqtrade/templates/FreqaiExampleStrategy.py
+++ b/freqtrade/templates/FreqaiExampleStrategy.py
@@ -290,9 +290,6 @@ class FreqaiExampleStrategy(IStrategy):
return df
- def get_ticker_indicator(self):
- return int(self.config["timeframe"][:-1])
-
def confirm_trade_entry(
self,
pair: str,
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 4bda09e2d..44cf0982d 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -7,7 +7,7 @@
-r docs/requirements-docs.txt
coveralls==3.3.1
-ruff==0.1.5
+ruff==0.1.6
mypy==1.7.0
pre-commit==3.5.0
pytest==7.4.3
diff --git a/requirements-freqai-rl.txt b/requirements-freqai-rl.txt
index c2cca5427..fba25d409 100644
--- a/requirements-freqai-rl.txt
+++ b/requirements-freqai-rl.txt
@@ -5,7 +5,7 @@
torch==2.0.1
#until these branches will be released we can use this
gymnasium==0.29.1
-stable_baselines3==2.1.0
+stable_baselines3==2.2.1
sb3_contrib>=2.0.0a9
# Progress bar for stable-baselines3 and sb3-contrib
tqdm==4.66.1
diff --git a/requirements-hyperopt.txt b/requirements-hyperopt.txt
index d1931eec1..b4bca9751 100644
--- a/requirements-hyperopt.txt
+++ b/requirements-hyperopt.txt
@@ -2,7 +2,7 @@
-r requirements.txt
# Required for hyperopt
-scipy==1.11.3
+scipy==1.11.4
scikit-learn==1.1.3
scikit-optimize==0.9.0
filelock==3.13.1
diff --git a/requirements.txt b/requirements.txt
index 63ae316a6..e3f2b4bbb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,9 +2,9 @@ numpy==1.26.2
pandas==2.1.3
pandas-ta==0.3.14b
-ccxt==4.1.52
+ccxt==4.1.57
cryptography==41.0.5
-aiohttp==3.8.6
+aiohttp==3.9.0
SQLAlchemy==2.0.23
python-telegram-bot==20.6
# can't be hard-pinned due to telegram-bot pinning httpx with ~
@@ -12,17 +12,16 @@ httpx>=0.24.1
arrow==1.3.0
cachetools==5.3.2
requests==2.31.0
-urllib3==2.0.7
-jsonschema==4.19.2
+urllib3==2.1.0
+jsonschema==4.20.0
TA-Lib==0.4.28
technical==1.4.0
tabulate==0.9.0
pycoingecko==3.1.0
jinja2==3.1.2
tables==3.9.1
-blosc==1.11.1
joblib==1.3.2
-rich==13.6.0
+rich==13.7.0
pyarrow==14.0.1; platform_machine != 'armv7l'
# find first, C search in arrays
@@ -38,7 +37,7 @@ sdnotify==0.3.2
# API Server
fastapi==0.104.1
-pydantic==2.4.2
+pydantic==2.5.1
uvicorn==0.24.0.post1
pyjwt==2.8.0
aiofiles==23.2.1
diff --git a/tests/exchange/test_exchange.py b/tests/exchange/test_exchange.py
index e2b3cc102..ad993cb6d 100644
--- a/tests/exchange/test_exchange.py
+++ b/tests/exchange/test_exchange.py
@@ -1851,7 +1851,7 @@ def test_fetch_bids_asks(default_conf, mocker):
@pytest.mark.parametrize("exchange_name", EXCHANGES)
-def test_get_tickers(default_conf, mocker, exchange_name):
+def test_get_tickers(default_conf, mocker, exchange_name, caplog):
api_mock = MagicMock()
tick = {'ETH/BTC': {
'symbol': 'ETH/BTC',
@@ -1900,6 +1900,14 @@ def test_get_tickers(default_conf, mocker, exchange_name):
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.get_tickers()
+ caplog.clear()
+ api_mock.fetch_tickers = MagicMock(side_effect=[ccxt.BadSymbol("SomeSymbol"), []])
+ exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
+ x = exchange.get_tickers()
+ assert x == []
+ assert log_has_re(r'Could not load tickers due to BadSymbol\..*SomeSymbol', caplog)
+ caplog.clear()
+
api_mock.fetch_tickers = MagicMock(return_value={})
exchange = get_patched_exchange(mocker, default_conf, api_mock, id=exchange_name)
exchange.get_tickers()
diff --git a/tests/exchange/test_exchange_utils.py b/tests/exchange/test_exchange_utils.py
index 377514468..8ae4039c7 100644
--- a/tests/exchange/test_exchange_utils.py
+++ b/tests/exchange/test_exchange_utils.py
@@ -18,7 +18,7 @@ from tests.conftest import log_has_re
def test_check_exchange(default_conf, caplog) -> None:
# Test an officially supported by Freqtrade team exchange
default_conf['runmode'] = RunMode.DRY_RUN
- default_conf.get('exchange').update({'name': 'BITTREX'})
+ default_conf.get('exchange').update({'name': 'BINANCE'})
assert check_exchange(default_conf)
assert log_has_re(r"Exchange .* is officially supported by the Freqtrade development team\.",
caplog)
diff --git a/tests/optimize/test_hyperopt.py b/tests/optimize/test_hyperopt.py
index b858aa33c..67f776c7e 100644
--- a/tests/optimize/test_hyperopt.py
+++ b/tests/optimize/test_hyperopt.py
@@ -310,6 +310,8 @@ def test_start_calls_optimizer(mocker, hyperopt_conf, capsys) -> None:
'freqtrade.optimize.hyperopt.get_timerange',
MagicMock(return_value=(datetime(2017, 12, 10), datetime(2017, 12, 13)))
)
+ # Dummy-reduce points to ensure scikit-learn is forced to generate new values
+ mocker.patch('freqtrade.optimize.hyperopt.INITIAL_POINTS', 2)
parallel = mocker.patch(
'freqtrade.optimize.hyperopt.Hyperopt.run_optimizer_parallel',
@@ -860,6 +862,8 @@ def test_simplified_interface_failed(mocker, hyperopt_conf, space) -> None:
def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmp_path, fee) -> None:
patch_exchange(mocker)
mocker.patch(f'{EXMS}.get_fee', fee)
+ # Dummy-reduce points to ensure scikit-learn is forced to generate new values
+ mocker.patch('freqtrade.optimize.hyperopt.INITIAL_POINTS', 2)
(tmp_path / 'hyperopt_results').mkdir(parents=True)
# No hyperopt needed
hyperopt_conf.update({
@@ -904,6 +908,8 @@ def test_in_strategy_auto_hyperopt_with_parallel(mocker, hyperopt_conf, tmp_path
mocker.patch(f'{EXMS}.markets',
PropertyMock(return_value=get_markets()))
(tmp_path / 'hyperopt_results').mkdir(parents=True)
+ # Dummy-reduce points to ensure scikit-learn is forced to generate new values
+ mocker.patch('freqtrade.optimize.hyperopt.INITIAL_POINTS', 2)
# No hyperopt needed
hyperopt_conf.update({
'strategy': 'HyperoptableStrategy',
diff --git a/tests/persistence/test_persistence.py b/tests/persistence/test_persistence.py
index 0fc8c7f47..5829f8b71 100644
--- a/tests/persistence/test_persistence.py
+++ b/tests/persistence/test_persistence.py
@@ -2676,9 +2676,9 @@ def test_order_to_ccxt(limit_buy_order_open, limit_sell_order_usdt_open):
'orders': [
(('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)),
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
- (('sell', 50, 12), (150.0, 12.5, 1875.0, -25.0, -25.0, -0.04)),
- (('sell', 100, 20), (50.0, 12.5, 625.0, 725.0, 750.0, 0.60)),
- (('sell', 50, 5), (50.0, 12.5, 625.0, 350.0, -375.0, -0.60)),
+ (('sell', 50, 12), (150.0, 12.5, 1875.0, -25.0, -25.0, -0.01)),
+ (('sell', 100, 20), (50.0, 12.5, 625.0, 725.0, 750.0, 0.29)),
+ (('sell', 50, 5), (50.0, 12.5, 625.0, 350.0, -375.0, 0.14)),
],
'end_profit': 350.0,
'end_profit_ratio': 0.14,
@@ -2688,9 +2688,9 @@ def test_order_to_ccxt(limit_buy_order_open, limit_sell_order_usdt_open):
'orders': [
(('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)),
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
- (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)),
- (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)),
- (('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, -377.1875, -0.60199501)),
+ (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.011197)),
+ (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.2848129)),
+ (('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, -377.1875, 0.1343142)),
],
'end_profit': 336.625,
'end_profit_ratio': 0.1343142,
@@ -2700,10 +2700,10 @@ def test_order_to_ccxt(limit_buy_order_open, limit_sell_order_usdt_open):
'orders': [
(('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)),
(('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)),
- (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)),
- (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)),
- (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)),
- (('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 1787.25, 1.08048062)),
+ (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 0.5945137)),
+ (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 0.5945137)),
+ (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.4261653)),
+ (('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 1787.25, 0.9747170)),
],
'end_profit': 3175.75,
'end_profit_ratio': 0.9747170,
@@ -2714,10 +2714,10 @@ def test_order_to_ccxt(limit_buy_order_open, limit_sell_order_usdt_open):
'orders': [
(('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)),
(('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)),
- (('sell', 100, 11), (100.0, 5.0, 500.0, 600.0, 600.0, 1.2)),
- (('buy', 150, 15), (250.0, 11.0, 2750.0, 600.0, 600.0, 1.2)),
- (('sell', 100, 19), (150.0, 11.0, 1650.0, 1400.0, 800.0, 0.72727273)),
- (('sell', 150, 23), (150.0, 11.0, 1650.0, 3200.0, 1800.0, 1.09090909)),
+ (('sell', 100, 11), (100.0, 5.0, 500.0, 600.0, 600.0, 0.6)),
+ (('buy', 150, 15), (250.0, 11.0, 2750.0, 600.0, 600.0, 0.6)),
+ (('sell', 100, 19), (150.0, 11.0, 1650.0, 1400.0, 800.0, 0.43076923)),
+ (('sell', 150, 23), (150.0, 11.0, 1650.0, 3200.0, 1800.0, 0.98461538)),
],
'end_profit': 3200.0,
'end_profit_ratio': 0.98461538,
@@ -2727,10 +2727,10 @@ def test_order_to_ccxt(limit_buy_order_open, limit_sell_order_usdt_open):
'orders': [
(('buy', 100, 8), (100.0, 8.0, 800.0, 0.0, None, None)),
(('buy', 100, 9), (200.0, 8.5, 1700.0, 0.0, None, None)),
- (('sell', 100, 10), (100.0, 8.5, 850.0, 150.0, 150.0, 0.17647059)),
- (('buy', 150, 11), (250.0, 10, 2500.0, 150.0, 150.0, 0.17647059)),
- (('sell', 100, 12), (150.0, 10.0, 1500.0, 350.0, 200.0, 0.2)),
- (('sell', 150, 14), (150.0, 10.0, 1500.0, 950.0, 600.0, 0.40)),
+ (('sell', 100, 10), (100.0, 8.5, 850.0, 150.0, 150.0, 0.08823529)),
+ (('buy', 150, 11), (250.0, 10, 2500.0, 150.0, 150.0, 0.08823529)),
+ (('sell', 100, 12), (150.0, 10.0, 1500.0, 350.0, 200.0, 0.1044776)),
+ (('sell', 150, 14), (150.0, 10.0, 1500.0, 950.0, 600.0, 0.283582)),
],
'end_profit': 950.0,
'end_profit_ratio': 0.283582,
diff --git a/tests/test_freqtradebot.py b/tests/test_freqtradebot.py
index 40d77ce6c..c9cb86cc0 100644
--- a/tests/test_freqtradebot.py
+++ b/tests/test_freqtradebot.py
@@ -6569,16 +6569,16 @@ def test_position_adjust2(mocker, default_conf_usdt, fee) -> None:
# tuple 2 - amount, open_rate, stake_amount, cumulative_profit, realized_profit, rel_profit
(('buy', 100, 10), (100.0, 10.0, 1000.0, 0.0, None, None)),
(('buy', 100, 15), (200.0, 12.5, 2500.0, 0.0, None, None)),
- (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.044788)),
- (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.59201995)),
+ (('sell', 50, 12), (150.0, 12.5, 1875.0, -28.0625, -28.0625, -0.011197)),
+ (('sell', 100, 20), (50.0, 12.5, 625.0, 713.8125, 741.875, 0.2848129)),
(('sell', 50, 5), (50.0, 12.5, 625.0, 336.625, 336.625, 0.1343142)), # final profit (sum)
),
(
(('buy', 100, 3), (100.0, 3.0, 300.0, 0.0, None, None)),
(('buy', 100, 7), (200.0, 5.0, 1000.0, 0.0, None, None)),
- (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 1.189027)),
- (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 1.189027)),
- (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.7186579)),
+ (('sell', 100, 11), (100.0, 5.0, 500.0, 596.0, 596.0, 0.5945137)),
+ (('buy', 150, 15), (250.0, 11.0, 2750.0, 596.0, 596.0, 0.5945137)),
+ (('sell', 100, 19), (150.0, 11.0, 1650.0, 1388.5, 792.5, 0.4261653)),
(('sell', 150, 23), (150.0, 11.0, 1650.0, 3175.75, 3175.75, 0.9747170)), # final profit
)
])
diff --git a/tests/test_integration.py b/tests/test_integration.py
index ee1d4bbb3..12647f6e2 100644
--- a/tests/test_integration.py
+++ b/tests/test_integration.py
@@ -1,3 +1,4 @@
+import time
from unittest.mock import MagicMock
import pytest
@@ -440,6 +441,7 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
assert trade.open_rate == 1.99
assert trade.orders[-1].price == 1.96
assert trade.orders[-1].cost == 120 * leverage
+ time.sleep(0.1)
# Replace new order with diff. order at a lower price
freqtrade.strategy.adjust_entry_price = MagicMock(return_value=1.95)
diff --git a/tests/testdata/config.tests.json b/tests/testdata/config.tests.json
new file mode 100644
index 000000000..fdfa97350
--- /dev/null
+++ b/tests/testdata/config.tests.json
@@ -0,0 +1,74 @@
+{
+ "max_open_trades": 3,
+ "stake_currency": "BTC",
+ "stake_amount": 0.05,
+ "tradable_balance_ratio": 0.99,
+ "fiat_display_currency": "USD",
+ "timeframe": "5m",
+ "dry_run": true,
+ "cancel_open_orders_on_exit": false,
+ "unfilledtimeout": {
+ "entry": 5,
+ "exit": 5,
+ "exit_timeout_count": 0,
+ "unit": "minutes"
+ },
+ "entry_pricing": {
+ "price_side": "same",
+ "use_order_book": true,
+ "order_book_top": 1,
+ "price_last_balance": 0.0,
+ "check_depth_of_market": {
+ "enabled": false,
+ "bids_to_ask_delta": 1
+ }
+ },
+ "exit_pricing":{
+ "price_side": "same",
+ "use_order_book": true,
+ "order_book_top": 1
+ },
+ "exchange": {
+ "name": "gate",
+ "key": "your_exchange_key",
+ "secret": "your_exchange_secret",
+ "ccxt_config": {},
+ "ccxt_async_config": {},
+ "pair_whitelist": [
+ "ETH/BTC",
+ "LTC/BTC",
+ "ETC/BTC",
+ "XLM/BTC",
+ "XRP/BTC",
+ "ADA/BTC",
+ "DOT/BTC"
+ ],
+ "pair_blacklist": [
+ "DOGE/BTC"
+ ]
+ },
+ "pairlists": [
+ {"method": "StaticPairList"}
+ ],
+ "telegram": {
+ "enabled": false,
+ "token": "your_telegram_token",
+ "chat_id": "your_telegram_chat_id"
+ },
+ "api_server": {
+ "enabled": false,
+ "listen_ip_address": "127.0.0.1",
+ "listen_port": 8080,
+ "verbosity": "error",
+ "jwt_secret_key": "somethingrandom",
+ "CORS_origins": [],
+ "username": "freqtrader",
+ "password": "SuperSecurePassword"
+ },
+ "bot_name": "freqtrade",
+ "initial_state": "running",
+ "force_entry_enable": false,
+ "internals": {
+ "process_throttle_secs": 5
+ }
+}