From 74ff9f551b1501765adcc567517cba0217e2d373 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 03:01:26 +0000 Subject: [PATCH 1/9] Bump ccxt from 1.77.45 to 1.77.97 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.77.45 to 1.77.97. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.77.45...1.77.97) --- updated-dependencies: - dependency-name: ccxt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d305f91b4..f2d04d485 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.3 pandas==1.4.1 pandas-ta==0.3.14b -ccxt==1.77.45 +ccxt==1.77.97 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 From 20f032601adb8f363a9ce77088545af577b18fe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 03:01:33 +0000 Subject: [PATCH 2/9] Bump sqlalchemy from 1.4.32 to 1.4.34 Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 1.4.32 to 1.4.34. - [Release notes](https://github.com/sqlalchemy/sqlalchemy/releases) - [Changelog](https://github.com/sqlalchemy/sqlalchemy/blob/main/CHANGES.rst) - [Commits](https://github.com/sqlalchemy/sqlalchemy/commits) --- updated-dependencies: - dependency-name: sqlalchemy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d305f91b4..d5e833df3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ ccxt==1.77.45 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 -SQLAlchemy==1.4.32 +SQLAlchemy==1.4.34 python-telegram-bot==13.11 arrow==1.2.2 cachetools==4.2.2 From 225f6d1525e3e73948cc6aa802fef175b2ab0990 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 03:01:35 +0000 Subject: [PATCH 3/9] Bump nbconvert from 6.4.4 to 6.4.5 Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 6.4.4 to 6.4.5. - [Release notes](https://github.com/jupyter/nbconvert/releases) - [Commits](https://github.com/jupyter/nbconvert/compare/6.4.4...6.4.5) --- updated-dependencies: - dependency-name: nbconvert dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 063cfaa45..c4340a836 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -17,7 +17,7 @@ isort==5.10.1 time-machine==2.6.0 # Convert jupyter notebooks to markdown documents -nbconvert==6.4.4 +nbconvert==6.4.5 # mypy types types-cachetools==5.0.0 From d668416d9c7e26b8f98e98813be41b0d02262b01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 03:01:37 +0000 Subject: [PATCH 4/9] Bump types-requests from 2.27.15 to 2.27.16 Bumps [types-requests](https://github.com/python/typeshed) from 2.27.15 to 2.27.16. - [Release notes](https://github.com/python/typeshed/releases) - [Commits](https://github.com/python/typeshed/commits) --- updated-dependencies: - dependency-name: types-requests dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 063cfaa45..9893fc91f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -22,7 +22,7 @@ nbconvert==6.4.4 # mypy types types-cachetools==5.0.0 types-filelock==3.2.5 -types-requests==2.27.15 +types-requests==2.27.16 types-tabulate==0.8.6 # Extensions to datetime library From d5ec95e8e020f9f29656f6dff4d0f699879fb9d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 03:01:46 +0000 Subject: [PATCH 5/9] Bump fastapi from 0.75.0 to 0.75.1 Bumps [fastapi](https://github.com/tiangolo/fastapi) from 0.75.0 to 0.75.1. - [Release notes](https://github.com/tiangolo/fastapi/releases) - [Commits](https://github.com/tiangolo/fastapi/compare/0.75.0...0.75.1) --- updated-dependencies: - dependency-name: fastapi dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d305f91b4..98b374309 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,7 +31,7 @@ python-rapidjson==1.6 sdnotify==0.3.2 # API Server -fastapi==0.75.0 +fastapi==0.75.1 uvicorn==0.17.6 pyjwt==2.3.0 aiofiles==0.8.0 From 655165ace0fb2d49cf20d69c351ca3edb36f3d5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 04:37:13 +0000 Subject: [PATCH 6/9] Bump ccxt from 1.77.97 to 1.77.98 Bumps [ccxt](https://github.com/ccxt/ccxt) from 1.77.97 to 1.77.98. - [Release notes](https://github.com/ccxt/ccxt/releases) - [Changelog](https://github.com/ccxt/ccxt/blob/master/exchanges.cfg) - [Commits](https://github.com/ccxt/ccxt/compare/1.77.97...1.77.98) --- updated-dependencies: - dependency-name: ccxt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 48909dc6b..dd8ecff84 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ numpy==1.22.3 pandas==1.4.1 pandas-ta==0.3.14b -ccxt==1.77.97 +ccxt==1.77.98 # Pin cryptography for now due to rust build errors with piwheels cryptography==36.0.2 aiohttp==3.8.1 From ef65bece7b03499b8571bcc0f6c14e7ecf2454c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Apr 2022 05:05:50 +0000 Subject: [PATCH 7/9] Bump pandas from 1.4.1 to 1.4.2 Bumps [pandas](https://github.com/pandas-dev/pandas) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/pandas-dev/pandas/releases) - [Changelog](https://github.com/pandas-dev/pandas/blob/main/RELEASE.md) - [Commits](https://github.com/pandas-dev/pandas/compare/v1.4.1...v1.4.2) --- updated-dependencies: - dependency-name: pandas dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index dd8ecff84..e09fb5925 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ numpy==1.22.3 -pandas==1.4.1 +pandas==1.4.2 pandas-ta==0.3.14b ccxt==1.77.98 From f8783c908ec3e29f79edb6f8e06ea0e9685c94c9 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 Apr 2022 16:48:27 +0200 Subject: [PATCH 8/9] Add side to custom_entry_price --- docs/strategy-callbacks.md | 2 +- docs/strategy_migration.md | 21 +++++++++++++++++++++ freqtrade/freqtradebot.py | 4 +++- freqtrade/optimize/backtesting.py | 4 +++- freqtrade/strategy/interface.py | 3 ++- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/docs/strategy-callbacks.md b/docs/strategy-callbacks.md index f265bfe61..7b8769f0c 100644 --- a/docs/strategy-callbacks.md +++ b/docs/strategy-callbacks.md @@ -365,7 +365,7 @@ class AwesomeStrategy(IStrategy): # ... populate_* methods def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, - entry_tag: Optional[str], **kwargs) -> float: + entry_tag: Optional[str], side: str, **kwargs) -> float: dataframe, last_updated = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe) diff --git a/docs/strategy_migration.md b/docs/strategy_migration.md index 40c1ee760..5721537c6 100644 --- a/docs/strategy_migration.md +++ b/docs/strategy_migration.md @@ -18,6 +18,7 @@ You can use the quick summary as checklist. Please refer to the detailed section * New `side` argument to callbacks without trade object * [`custom_stake_amount`](#custom-stake-amount) * [`confirm_trade_entry`](#confirm_trade_entry) + * [`custom_entry_price`](#custom_entry_price) * [Changed argument name in `confirm_trade_exit`](#confirm_trade_exit) * Dataframe columns: * [`buy` -> `enter_long`](#populate_buy_trend) @@ -227,6 +228,26 @@ class AwesomeStrategy(IStrategy): return True ``` +### `custom_entry_price` + +New string argument `side` - which can be either `"long"` or `"short"`. + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, + entry_tag: Optional[str], **kwargs) -> float: + return proposed_rate +``` + +After: + +``` python hl_lines="3" +class AwesomeStrategy(IStrategy): + def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, + entry_tag: Optional[str], side: str, **kwargs) -> float: + return proposed_rate +``` + ### Adjust trade position changes While adjust-trade-position itself did not change, you should no longer use `trade.nr_of_successful_buys` - and instead use `trade.nr_of_successful_entries`, which will also include short entries. diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 95a728c99..9e01a150c 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -760,7 +760,9 @@ class FreqtradeBot(LoggingMixin): custom_entry_price = strategy_safe_wrapper(self.strategy.custom_entry_price, default_retval=proposed_enter_rate)( pair=pair, current_time=datetime.now(timezone.utc), - proposed_rate=proposed_enter_rate, entry_tag=entry_tag) + proposed_rate=proposed_enter_rate, entry_tag=entry_tag, + side=trade_side, + ) enter_limit_requested = self.get_valid_price(custom_entry_price, proposed_enter_rate) diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index 943426679..aab340c21 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -643,7 +643,9 @@ class Backtesting: propose_rate = strategy_safe_wrapper(self.strategy.custom_entry_price, default_retval=propose_rate)( pair=pair, current_time=current_time, - proposed_rate=propose_rate, entry_tag=entry_tag) # default value is the open rate + proposed_rate=propose_rate, entry_tag=entry_tag, + side=direction, + ) # default value is the open rate # We can't place orders higher than current high (otherwise it'd be a stop limit buy) # which freqtrade does not support in live. if direction == "short": diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 30ac4f355..508aa5c73 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -339,7 +339,7 @@ class IStrategy(ABC, HyperStrategyMixin): return self.stoploss def custom_entry_price(self, pair: str, current_time: datetime, proposed_rate: float, - entry_tag: Optional[str], **kwargs) -> float: + entry_tag: Optional[str], side: str, **kwargs) -> float: """ Custom entry price logic, returning the new entry price. @@ -351,6 +351,7 @@ class IStrategy(ABC, HyperStrategyMixin): :param current_time: datetime object, containing the current datetime :param proposed_rate: Rate, calculated based on pricing settings in exit_pricing. :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal. + :param side: 'long' or 'short' - indicating the direction of the proposed trade :param **kwargs: Ensure to keep this here so updates to this won't break your strategy. :return float: New entry price value if provided """ From 33841da382a3b8071fdfec407573b3700f28e010 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 4 Apr 2022 16:51:57 +0200 Subject: [PATCH 9/9] Slightly imporve Typing by reusing long/short type --- freqtrade/constants.py | 5 ++++- freqtrade/exchange/exchange.py | 4 ++-- freqtrade/freqtradebot.py | 7 ++++--- freqtrade/optimize/backtesting.py | 8 ++++---- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/freqtrade/constants.py b/freqtrade/constants.py index a06e2771f..d927f03d7 100644 --- a/freqtrade/constants.py +++ b/freqtrade/constants.py @@ -3,7 +3,7 @@ """ bot constants """ -from typing import List, Tuple +from typing import List, Literal, Tuple from freqtrade.enums import CandleType @@ -487,3 +487,6 @@ ListPairsWithTimeframes = List[PairWithTimeframe] # Type for trades list TradeList = List[List] + +LongShort = Literal['long', 'short'] +EntryExit = Literal['entry', 'exit'] diff --git a/freqtrade/exchange/exchange.py b/freqtrade/exchange/exchange.py index 09ada4452..609dbb83e 100644 --- a/freqtrade/exchange/exchange.py +++ b/freqtrade/exchange/exchange.py @@ -20,7 +20,7 @@ from ccxt.base.decimal_to_precision import (ROUND_DOWN, ROUND_UP, TICK_SIZE, TRU from pandas import DataFrame from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES, - ListPairsWithTimeframes, PairWithTimeframe) + EntryExit, ListPairsWithTimeframes, PairWithTimeframe) from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list from freqtrade.enums import OPTIMIZE_MODES, CandleType, MarginMode, TradingMode from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError, @@ -1429,7 +1429,7 @@ class Exchange: raise OperationalException(e) from e def get_rate(self, pair: str, refresh: bool, - side: Literal['entry', 'exit'], is_short: bool) -> float: + side: EntryExit, is_short: bool) -> float: """ Calculates bid/ask target bid rate - between current ask price and last price diff --git a/freqtrade/freqtradebot.py b/freqtrade/freqtradebot.py index 9e01a150c..f440d8b99 100644 --- a/freqtrade/freqtradebot.py +++ b/freqtrade/freqtradebot.py @@ -7,12 +7,13 @@ import traceback from datetime import datetime, time, timezone from math import isclose from threading import Lock -from typing import Any, Dict, List, Literal, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple from schedule import Scheduler from freqtrade import __version__, constants from freqtrade.configuration import validate_config_consistency +from freqtrade.constants import LongShort from freqtrade.data.converter import order_book_to_dataframe from freqtrade.data.dataprovider import DataProvider from freqtrade.edge import Edge @@ -590,7 +591,7 @@ class FreqtradeBot(LoggingMixin): time_in_force = self.strategy.order_time_in_force['entry'] [side, name] = ['sell', 'Short'] if is_short else ['buy', 'Long'] - trade_side: Literal['long', 'short'] = 'short' if is_short else 'long' + trade_side: LongShort = 'short' if is_short else 'long' pos_adjust = trade is not None enter_limit_requested, stake_amount, leverage = self.get_valid_enter_price_and_stake( @@ -746,7 +747,7 @@ class FreqtradeBot(LoggingMixin): def get_valid_enter_price_and_stake( self, pair: str, price: Optional[float], stake_amount: float, - trade_side: Literal['long', 'short'], + trade_side: LongShort, entry_tag: Optional[str], trade: Optional[Trade] ) -> Tuple[float, float, float]: diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index aab340c21..2a5c0fabd 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -14,7 +14,7 @@ from pandas import DataFrame from freqtrade import constants from freqtrade.configuration import TimeRange, validate_config_consistency -from freqtrade.constants import DATETIME_PRINT_FORMAT +from freqtrade.constants import DATETIME_PRINT_FORMAT, LongShort from freqtrade.data import history from freqtrade.data.btanalysis import find_existing_backtest_stats, trade_list_to_dataframe from freqtrade.data.converter import trim_dataframe, trim_dataframes @@ -635,7 +635,7 @@ class Backtesting: def get_valid_price_and_stake( self, pair: str, row: Tuple, propose_rate: float, stake_amount: Optional[float], - direction: str, current_time: datetime, entry_tag: Optional[str], + direction: LongShort, current_time: datetime, entry_tag: Optional[str], trade: Optional[LocalTrade], order_type: str ) -> Tuple[float, float, float, float]: @@ -696,7 +696,7 @@ class Backtesting: return propose_rate, stake_amount_val, leverage, min_stake_amount - def _enter_trade(self, pair: str, row: Tuple, direction: str, + def _enter_trade(self, pair: str, row: Tuple, direction: LongShort, stake_amount: Optional[float] = None, trade: Optional[LocalTrade] = None) -> Optional[LocalTrade]: @@ -829,7 +829,7 @@ class Backtesting: self.rejected_trades += 1 return False - def check_for_trade_entry(self, row) -> Optional[str]: + def check_for_trade_entry(self, row) -> Optional[LongShort]: enter_long = row[LONG_IDX] == 1 exit_long = row[ELONG_IDX] == 1 enter_short = self._can_short and row[SHORT_IDX] == 1