Merge branch 'freqtrade:develop' into develop

This commit is contained in:
hippocritical
2023-04-18 16:55:10 +02:00
committed by GitHub
23 changed files with 990 additions and 422 deletions

View File

@@ -57,7 +57,7 @@ jobs:
- name: Installation - *nix
if: runner.os == 'Linux'
run: |
python -m pip install --upgrade pip wheel
python -m pip install --upgrade pip==23.0.1 wheel
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
export TA_INCLUDE_PATH=${HOME}/dependencies/include
@@ -163,7 +163,7 @@ jobs:
rm /usr/local/bin/python3.11-config || true
brew install hdf5 c-blosc
python -m pip install --upgrade pip wheel
python -m pip install --upgrade pip==23.0.1 wheel
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
export TA_INCLUDE_PATH=${HOME}/dependencies/include
@@ -352,7 +352,7 @@ jobs:
- name: Installation - *nix
if: runner.os == 'Linux'
run: |
python -m pip install --upgrade pip wheel
python -m pip install --upgrade pip==23.0.1 wheel
export LD_LIBRARY_PATH=${HOME}/dependencies/lib:$LD_LIBRARY_PATH
export TA_LIBRARY_PATH=${HOME}/dependencies/lib
export TA_INCLUDE_PATH=${HOME}/dependencies/include

View File

@@ -25,7 +25,7 @@ FROM base as python-deps
RUN apt-get update \
&& apt-get -y install build-essential libssl-dev git libffi-dev libgfortran5 pkg-config cmake gcc \
&& apt-get clean \
&& pip install --upgrade pip
&& pip install --upgrade pip==23.0.1
# Install TA-lib
COPY build_helpers/* /tmp/

View File

@@ -1,7 +1,7 @@
# Downloads don't work automatically, since the URL is regenerated via javascript.
# Downloaded from https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib
python -m pip install --upgrade pip wheel
python -m pip install --upgrade pip==23.0.1 wheel
$pyv = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"

View File

@@ -85,6 +85,7 @@ Mandatory parameters are marked as **Required** and have to be set in one of the
| `net_arch` | Network architecture which is well described in [`stable_baselines3` doc](https://stable-baselines3.readthedocs.io/en/master/guide/custom_policy.html#examples). In summary: `[<shared layers>, dict(vf=[<non-shared value network layers>], pi=[<non-shared policy network layers>])]`. By default this is set to `[128, 128]`, which defines 2 shared hidden layers with 128 units each.
| `randomize_starting_position` | Randomize the starting point of each episode to avoid overfitting. <br> **Datatype:** bool. <br> Default: `False`.
| `drop_ohlc_from_features` | Do not include the normalized ohlc data in the feature set passed to the agent during training (ohlc will still be used for driving the environment in all cases) <br> **Datatype:** Boolean. <br> **Default:** `False`
| `progress_bar` | Display a progress bar with the current progress, elapsed time and estimated remaining time. <br> **Datatype:** Boolean. <br> Default: `False`.
### PyTorch parameters

View File

@@ -600,6 +600,7 @@ CONF_SCHEMA = {
"policy_type": {"type": "string", "default": "MlpPolicy"},
"net_arch": {"type": "array", "default": [128, 128]},
"randomize_starting_position": {"type": "boolean", "default": False},
"progress_bar": {"type": "boolean", "default": True},
"model_reward_parameters": {
"type": "object",
"properties": {

View File

@@ -6,6 +6,7 @@ from freqtrade.exchange.exchange import Exchange
from freqtrade.exchange.binance import Binance
from freqtrade.exchange.bitpanda import Bitpanda
from freqtrade.exchange.bittrex import Bittrex
from freqtrade.exchange.bitvavo import Bitvavo
from freqtrade.exchange.bybit import Bybit
from freqtrade.exchange.coinbasepro import Coinbasepro
from freqtrade.exchange.exchange_utils import (ROUND_DOWN, ROUND_UP, amount_to_contract_precision,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
"""Kucoin exchange subclass."""
import logging
from typing import Dict
from freqtrade.exchange import Exchange
logger = logging.getLogger(__name__)
class Bitvavo(Exchange):
"""Bitvavo exchange class.
Contains adjustments needed for Freqtrade to work with this exchange.
Please note that this exchange is not included in the list of exchanges
officially supported by the Freqtrade development team. So some features
may still not work as expected.
"""
_ft_has: Dict = {
"ohlcv_candle_limit": 1440,
}

View File

@@ -2371,12 +2371,12 @@ class Exchange:
# Must fetch the leverage tiers for each market separately
# * This is slow(~45s) on Okx, makes ~90 api calls to load all linear swap markets
markets = self.markets
symbols = []
for symbol, market in markets.items():
symbols = [
symbol for symbol, market in markets.items()
if (self.market_is_future(market)
and market['quote'] == self._config['stake_currency']):
symbols.append(symbol)
and market['quote'] == self._config['stake_currency'])
]
tiers: Dict[str, List[Dict]] = {}
@@ -2396,25 +2396,26 @@ class Exchange:
else:
logger.info("Using cached leverage_tiers.")
async def gather_results():
async def gather_results(input_coro):
return await asyncio.gather(*input_coro, return_exceptions=True)
for input_coro in chunks(coros, 100):
with self._loop_lock:
results = self.loop.run_until_complete(gather_results())
results = self.loop.run_until_complete(gather_results(input_coro))
for symbol, res in results:
tiers[symbol] = res
for res in results:
if isinstance(res, Exception):
logger.warning(f"Leverage tier exception: {repr(res)}")
continue
symbol, tier = res
tiers[symbol] = tier
if len(coros) > 0:
self.cache_leverage_tiers(tiers, self._config['stake_currency'])
logger.info(f"Done initializing {len(symbols)} markets.")
return tiers
else:
return {}
else:
return {}
return {}
def cache_leverage_tiers(self, tiers: Dict[str, List[Dict]], stake_currency: str) -> None:

View File

@@ -71,7 +71,8 @@ class ReinforcementLearner(BaseReinforcementLearningModel):
model.learn(
total_timesteps=int(total_timesteps),
callback=[self.eval_callback, self.tensorboard_callback]
callback=[self.eval_callback, self.tensorboard_callback],
progress_bar=self.rl_config.get('progress_bar', False)
)
if Path(dk.data_path / "best_model.zip").is_file():

View File

@@ -273,7 +273,8 @@ def _get_resample_from_period(period: str) -> str:
if period == 'day':
return '1d'
if period == 'week':
return '1w'
# Weekly defaulting to Monday.
return '1W-MON'
if period == 'month':
return '1M'
raise ValueError(f"Period {period} is not supported.")

View File

@@ -68,6 +68,9 @@ target-version = "py38"
extend-select = [
"C90", # mccabe
# "N", # pep8-naming
"F", # pyflakes
"E", # pycodestyle
"W", # pycodestyle
"UP", # pyupgrade
"TID", # flake8-tidy-imports
# "EXE", # flake8-executable

View File

@@ -10,7 +10,7 @@ coveralls==3.3.1
ruff==0.0.261
mypy==1.2.0
pre-commit==3.2.2
pytest==7.3.0
pytest==7.3.1
pytest-asyncio==0.21.0
pytest-cov==4.0.0
pytest-mock==3.10.0
@@ -19,7 +19,7 @@ isort==5.12.0
# For datetime mocking
time-machine==2.9.0
# fastapi testing
httpx==0.23.3
httpx==0.24.0
# Convert jupyter notebooks to markdown documents
nbconvert==7.3.1

View File

@@ -8,3 +8,5 @@ sb3-contrib==1.7.0; python_version < '3.11'
# Gym is forced to this version by stable-baselines3.
setuptools==65.5.1 # Should be removed when gym is fixed.
gym==0.21; python_version < '3.11'
# Progress bar for stable-baselines3 and sb3-contrib
tqdm==4.65.0; python_version < '3.11'

View File

@@ -8,4 +8,4 @@ joblib==1.2.0
catboost==1.1.1; platform_machine != 'aarch64' and 'arm' not in platform_machine and python_version < '3.11'
lightgbm==3.3.5
xgboost==1.7.5
tensorboard==2.12.1
tensorboard==2.12.2

View File

@@ -2,8 +2,8 @@ numpy==1.24.2
pandas==1.5.3
pandas-ta==0.3.14b
ccxt==3.0.59
cryptography==40.0.1
ccxt==3.0.69
cryptography==40.0.2
aiohttp==3.8.4
SQLAlchemy==2.0.9
python-telegram-bot==13.15
@@ -20,7 +20,7 @@ jinja2==3.1.2
tables==3.8.0
blosc==1.11.1
joblib==1.2.0
rich==13.3.3
rich==13.3.4
pyarrow==11.0.0; platform_machine != 'armv7l'
# find first, C search in arrays
@@ -35,7 +35,7 @@ orjson==3.8.10
sdnotify==0.3.2
# API Server
fastapi==0.95.0
fastapi==0.95.1
pydantic==1.10.7
uvicorn==0.21.1
pyjwt==2.6.0

View File

@@ -50,7 +50,7 @@ function updateenv() {
SYS_ARCH=$(uname -m)
echo "pip install in-progress. Please wait..."
# Setuptools 65.5.0 is the last version that can install gym==0.21.0
${PYTHON} -m pip install --upgrade pip wheel setuptools==65.5.1
${PYTHON} -m pip install --upgrade pip==23.0.1 wheel setuptools==65.5.1
REQUIREMENTS_HYPEROPT=""
REQUIREMENTS_PLOT=""
REQUIREMENTS_FREQAI=""

View File

@@ -504,7 +504,7 @@ def get_default_conf(testdatadir):
{"method": "StaticPairList"}
],
"telegram": {
"enabled": True,
"enabled": False,
"token": "token",
"chat_id": "0",
"notification_settings": {},

View File

@@ -528,9 +528,11 @@ class TestCCXTExchange():
assert res[1] == timeframe
assert res[2] == candle_type
candles = res[3]
candle_count = exchange.ohlcv_candle_limit(timeframe, candle_type, since_ms) * 0.9
candle_count1 = (now.timestamp() * 1000 - since_ms) // timeframe_ms
assert len(candles) >= min(candle_count, candle_count1)
factor = 0.9
candle_count = exchange.ohlcv_candle_limit(timeframe, candle_type, since_ms) * factor
candle_count1 = (now.timestamp() * 1000 - since_ms) // timeframe_ms * factor
assert len(candles) >= min(candle_count, candle_count1), \
f"{len(candles)} < {candle_count} in {timeframe}, Offset: {offset} {factor}"
assert candles[0][0] == since_ms or (since_ms + timeframe_ms)
def test_ccxt__async_get_candle_history(self, exchange: EXCHANGE_FIXTURE_TYPE):

View File

@@ -1,14 +1,14 @@
from datetime import datetime, timedelta, timezone
from pathlib import Path
from unittest.mock import MagicMock, PropertyMock
from unittest.mock import AsyncMock, MagicMock, PropertyMock
import ccxt
import pytest
from freqtrade.enums import CandleType, MarginMode, TradingMode
from freqtrade.exceptions import RetryableOrderError
from freqtrade.exceptions import RetryableOrderError, TemporaryError
from freqtrade.exchange.exchange import timeframe_to_minutes
from tests.conftest import EXMS, get_mock_coro, get_patched_exchange, log_has
from tests.conftest import EXMS, get_patched_exchange, log_has
from tests.exchange.test_exchange import ccxt_exceptionhandlers
@@ -278,7 +278,7 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets, tmpdir, caplog,
'fetchLeverageTiers': False,
'fetchMarketLeverageTiers': True,
})
api_mock.fetch_market_leverage_tiers = get_mock_coro(side_effect=[
api_mock.fetch_market_leverage_tiers = AsyncMock(side_effect=[
[
{
'tier': 1,
@@ -341,6 +341,7 @@ def test_load_leverage_tiers_okx(default_conf, mocker, markets, tmpdir, caplog,
}
},
],
TemporaryError("this Failed"),
[
{
'tier': 1,

View File

@@ -465,7 +465,7 @@ def test_generate_periodic_breakdown_stats(testdatadir):
def test__get_resample_from_period():
assert _get_resample_from_period('day') == '1d'
assert _get_resample_from_period('week') == '1w'
assert _get_resample_from_period('week') == '1W-MON'
assert _get_resample_from_period('month') == '1M'
with pytest.raises(ValueError, match=r"Period noooo is not supported."):
_get_resample_from_period('noooo')

View File

@@ -28,6 +28,7 @@ def test_init_telegram_disabled(mocker, default_conf, caplog) -> None:
def test_init_telegram_enabled(mocker, default_conf, caplog) -> None:
caplog.set_level(logging.DEBUG)
default_conf['telegram']['enabled'] = True
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
rpc_manager = RPCManager(get_patched_freqtradebot(mocker, default_conf))
@@ -52,6 +53,7 @@ def test_cleanup_telegram_disabled(mocker, default_conf, caplog) -> None:
def test_cleanup_telegram_enabled(mocker, default_conf, caplog) -> None:
caplog.set_level(logging.DEBUG)
default_conf['telegram']['enabled'] = True
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.cleanup', MagicMock())
@@ -85,7 +87,7 @@ def test_send_msg_telegram_disabled(mocker, default_conf, caplog) -> None:
def test_send_msg_telegram_error(mocker, default_conf, caplog) -> None:
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())
mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', side_effect=ValueError())
default_conf['telegram']['enabled'] = True
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
rpc_manager = RPCManager(freqtradebot)
rpc_manager.send_msg({
@@ -99,6 +101,7 @@ def test_send_msg_telegram_error(mocker, default_conf, caplog) -> None:
def test_process_msg_queue(mocker, default_conf, caplog) -> None:
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
default_conf['telegram']['enabled'] = True
default_conf['telegram']['allow_custom_messages'] = True
mocker.patch('freqtrade.rpc.telegram.Telegram._init')
@@ -115,9 +118,9 @@ def test_process_msg_queue(mocker, default_conf, caplog) -> None:
def test_send_msg_telegram_enabled(mocker, default_conf, caplog) -> None:
default_conf['telegram']['enabled'] = True
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg')
mocker.patch('freqtrade.rpc.telegram.Telegram._init')
freqtradebot = get_patched_freqtradebot(mocker, default_conf)
rpc_manager = RPCManager(freqtradebot)
rpc_manager.send_msg({
@@ -166,7 +169,8 @@ def test_send_msg_webhook_CustomMessagetype(mocker, default_conf, caplog) -> Non
caplog)
def test_startupmessages_telegram_enabled(mocker, default_conf, caplog) -> None:
def test_startupmessages_telegram_enabled(mocker, default_conf) -> None:
default_conf['telegram']['enabled'] = True
telegram_mock = mocker.patch('freqtrade.rpc.telegram.Telegram.send_msg', MagicMock())
mocker.patch('freqtrade.rpc.telegram.Telegram._init', MagicMock())

View File

@@ -36,6 +36,13 @@ from tests.conftest import (CURRENT_TEST_STRATEGY, EXMS, create_mock_trades,
patch_exchange, patch_get_signal, patch_whitelist)
@pytest.fixture
def default_conf(default_conf) -> dict:
# Telegram is enabled by default
default_conf['telegram']['enabled'] = True
return default_conf
class DummyCls(Telegram):
"""
Dummy class for testing the Telegram @authorized_only decorator