mirror of
https://github.com/freqtrade/freqtrade.git
synced 2026-01-20 05:50:36 +00:00
Merge branch 'freqtrade:develop' into bt-metrics
This commit is contained in:
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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/.*"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. <br> **Datatype:** Dictionary.
|
||||
| `train_cycles` | Training time steps will be set based on the `train_cycles * number of training data points. <br> **Datatype:** Integer.
|
||||
| `cpu_count` | Number of processors to dedicate to the Reinforcement Learning training process. <br> **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. <br> **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) <br> **Datatype:** string.
|
||||
| `policy_type` | One of the available policy types from stable_baselines3 <br> **Datatype:** string.
|
||||
|
||||
@@ -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/)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -108,7 +108,6 @@ def ask_user_config() -> Dict[str, Any]:
|
||||
"choices": [
|
||||
"binance",
|
||||
"binanceus",
|
||||
"bittrex",
|
||||
"gate",
|
||||
"huobi",
|
||||
"kraken",
|
||||
|
||||
@@ -52,7 +52,6 @@ MAP_EXCHANGE_CHILDCLASS = {
|
||||
|
||||
SUPPORTED_EXCHANGES = [
|
||||
'binance',
|
||||
'bittrex',
|
||||
'gate',
|
||||
'huobi',
|
||||
'kraken',
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
)
|
||||
])
|
||||
|
||||
@@ -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)
|
||||
|
||||
74
tests/testdata/config.tests.json
vendored
Normal file
74
tests/testdata/config.tests.json
vendored
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user