Compare commits

...

40 Commits

Author SHA1 Message Date
Axel CH
a5a4006a38
Merge 6b8ca7217b into 2fe67edab3 2024-09-16 15:56:23 -04:00
Matthias
2fe67edab3 chore: update link to okx liquidation formula
Some checks failed
Build Documentation / Deploy Docs through mike (push) Waiting to run
Pre-commit auto-update / auto-update (push) Has been cancelled
2024-09-16 19:05:00 +02:00
Matthias
167e43cbef
Merge pull request #10655 from freqtrade/dependabot/pip/develop/types-dda07fe7e8
Some checks are pending
Build Documentation / Deploy Docs through mike (push) Waiting to run
chore(deps-dev): bump types-requests from 2.32.0.20240907 to 2.32.0.20240914 in the types group
2024-09-16 11:12:07 +02:00
Matthias
d8cb407c25
Merge pull request #10666 from freqtrade/dependabot/pip/develop/pydantic-2.9.1
chore(deps): bump pydantic from 2.9.0 to 2.9.1
2024-09-16 10:56:51 +02:00
Matthias
9452afe3f7
Merge pull request #10660 from freqtrade/dependabot/pip/develop/ruff-0.6.5
chore(deps-dev): bump ruff from 0.6.4 to 0.6.5
2024-09-16 10:21:12 +02:00
Matthias
8dc6d9ce7d
Merge pull request #10665 from freqtrade/dependabot/pip/develop/rich-13.8.1
chore(deps): bump rich from 13.8.0 to 13.8.1
2024-09-16 09:45:01 +02:00
Matthias
bf4b8a318d
Merge pull request #10661 from freqtrade/dependabot/pip/develop/scikit-learn-1.5.2
chore(deps): bump scikit-learn from 1.5.1 to 1.5.2
2024-09-16 09:44:31 +02:00
Matthias
20f6022050
Merge pull request #10663 from freqtrade/dependabot/pip/develop/ccxt-4.4.3
chore(deps): bump ccxt from 4.3.98 to 4.4.3
2024-09-16 09:33:16 +02:00
dependabot[bot]
65e6c737cd
chore(deps): bump pydantic from 2.9.0 to 2.9.1
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.9.0 to 2.9.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.9.0...v2.9.1)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 07:07:06 +00:00
Matthias
6d2572e347
Merge pull request #10662 from freqtrade/dependabot/pip/develop/fastapi-0.114.2
Some checks are pending
Build Documentation / Deploy Docs through mike (push) Waiting to run
chore(deps): bump fastapi from 0.114.0 to 0.114.2
2024-09-16 09:06:12 +02:00
Matthias
52a35197c7
Merge pull request #10659 from freqtrade/dependabot/pip/develop/pytz-2024.2
chore(deps): bump pytz from 2024.1 to 2024.2
2024-09-16 08:33:08 +02:00
Matthias
2b3a41db3e
Merge pull request #10658 from freqtrade/dependabot/pip/develop/urllib3-2.2.3
chore(deps): bump urllib3 from 2.2.2 to 2.2.3
2024-09-16 08:32:52 +02:00
dependabot[bot]
09c1459411
chore(deps-dev): bump ruff from 0.6.4 to 0.6.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.4 to 0.6.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.4...0.6.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 06:17:40 +00:00
Matthias
98f18b89da
Merge pull request #10657 from freqtrade/dependabot/pip/develop/plotly-5.24.1
chore(deps): bump plotly from 5.24.0 to 5.24.1
2024-09-16 08:16:56 +02:00
Matthias
4249db4330
Merge pull request #10656 from freqtrade/dependabot/pip/develop/pytest-baa91b6655
chore(deps-dev): bump pytest from 8.3.2 to 8.3.3 in the pytest group
2024-09-16 08:16:43 +02:00
Matthias
a7f46500ed
chore: bump types-requests in pre-commit 2024-09-16 06:38:45 +02:00
dependabot[bot]
c73fa2b0eb
chore(deps): bump rich from 13.8.0 to 13.8.1
Bumps [rich](https://github.com/Textualize/rich) from 13.8.0 to 13.8.1.
- [Release notes](https://github.com/Textualize/rich/releases)
- [Changelog](https://github.com/Textualize/rich/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Textualize/rich/compare/v13.8.0...v13.8.1)

---
updated-dependencies:
- dependency-name: rich
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:18:09 +00:00
dependabot[bot]
db4c4b971a
chore(deps): bump ccxt from 4.3.98 to 4.4.3
Bumps [ccxt](https://github.com/ccxt/ccxt) from 4.3.98 to 4.4.3.
- [Release notes](https://github.com/ccxt/ccxt/releases)
- [Changelog](https://github.com/ccxt/ccxt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ccxt/ccxt/compare/4.3.98...4.4.3)

---
updated-dependencies:
- dependency-name: ccxt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:58 +00:00
dependabot[bot]
e9ccc98ada
chore(deps): bump fastapi from 0.114.0 to 0.114.2
Bumps [fastapi](https://github.com/fastapi/fastapi) from 0.114.0 to 0.114.2.
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](https://github.com/fastapi/fastapi/compare/0.114.0...0.114.2)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:46 +00:00
dependabot[bot]
11d6ec33b3
chore(deps): bump scikit-learn from 1.5.1 to 1.5.2
Bumps [scikit-learn](https://github.com/scikit-learn/scikit-learn) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/scikit-learn/scikit-learn/releases)
- [Commits](https://github.com/scikit-learn/scikit-learn/compare/1.5.1...1.5.2)

---
updated-dependencies:
- dependency-name: scikit-learn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:39 +00:00
dependabot[bot]
c3b6f4ca85
chore(deps): bump pytz from 2024.1 to 2024.2
Bumps [pytz](https://github.com/stub42/pytz) from 2024.1 to 2024.2.
- [Release notes](https://github.com/stub42/pytz/releases)
- [Commits](https://github.com/stub42/pytz/compare/release_2024.1...release_2024.2)

---
updated-dependencies:
- dependency-name: pytz
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:21 +00:00
dependabot[bot]
d37405a307
chore(deps): bump urllib3 from 2.2.2 to 2.2.3
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.2 to 2.2.3.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.2.2...2.2.3)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:05 +00:00
dependabot[bot]
d7a9841328
chore(deps): bump plotly from 5.24.0 to 5.24.1
Bumps [plotly](https://github.com/plotly/plotly.py) from 5.24.0 to 5.24.1.
- [Release notes](https://github.com/plotly/plotly.py/releases)
- [Changelog](https://github.com/plotly/plotly.py/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plotly/plotly.py/compare/v5.24.0...v5.24.1)

---
updated-dependencies:
- dependency-name: plotly
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:17:01 +00:00
dependabot[bot]
cf3af42477
chore(deps-dev): bump pytest from 8.3.2 to 8.3.3 in the pytest group
Bumps the pytest group with 1 update: [pytest](https://github.com/pytest-dev/pytest).


Updates `pytest` from 8.3.2 to 8.3.3
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: pytest
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:16:39 +00:00
dependabot[bot]
ad8e6e7d67
chore(deps-dev): bump types-requests in the types group
Bumps the types group with 1 update: [types-requests](https://github.com/python/typeshed).


Updates `types-requests` from 2.32.0.20240907 to 2.32.0.20240914
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: types-requests
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: types
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 03:15:58 +00:00
Axel-CH
6b8ca7217b flake8 fix and cleanup 2024-09-11 21:48:48 -04:00
Axel-CH
2811a470aa handle pre existing open order cancelation on trade exit 2024-09-11 21:11:20 -04:00
Axel-CH
1fccdd8cda fix test_exit_positions 2024-09-11 18:59:29 -04:00
Axel-CH
33b421014d remove irrelevant trade.has_open_orders conditions 2024-09-11 18:42:51 -04:00
Axel-CH
730bef2920 add comments and logs for failing test, create untied_assets propertyto Trade 2024-09-09 19:28:04 -04:00
Axel-CH
79ce1ddaef rollback on process_open_trade_positions. Adjust position only if there is no open order, change will be made on other PR 2024-09-09 13:30:07 -04:00
Axel-CH
714822c93c add ETC/BTC pair to conftest get_markets 2024-09-09 13:15:17 -04:00
Axel-CH
fb3787173f fix test_exit_positions_exception 2024-09-09 12:07:50 -04:00
Axel-CH
e9ba0d2ce8 Merge remote-tracking branch 'origin/develop' into feature/proceed-exit-while-open-order 2024-09-06 17:29:07 -04:00
Axel-CH
6a580176ea Merge branch 'develop' into feature/proceed-exit-while-open-order 2024-07-01 17:49:40 -04:00
Axel-CH
910b3ad536 allow adjust trade position, even if there is an open order 2024-04-15 15:40:57 -04:00
Axel-CH
05cf4cab8e add has_open_entry_orders property to trade 2024-04-15 15:18:39 -04:00
Axel-CH
6752c3e288 add has_untied_assets, replace one has_open_orders condition by has_untied_assets in exit_positions 2024-04-15 14:43:40 -04:00
Axel-CH
faeda2a166 fix mypy error on has_open_position function 2024-04-14 00:40:12 -04:00
Axel-CH
3d67e0893a edit backtest_loop to check exit if trade has open position 2024-04-14 00:25:40 -04:00
13 changed files with 157 additions and 44 deletions

View File

@ -16,7 +16,7 @@ repos:
additional_dependencies: additional_dependencies:
- types-cachetools==5.5.0.20240820 - types-cachetools==5.5.0.20240820
- types-filelock==3.2.7 - types-filelock==3.2.7
- types-requests==2.32.0.20240907 - types-requests==2.32.0.20240914
- types-tabulate==0.9.0.20240106 - types-tabulate==0.9.0.20240106
- types-python-dateutil==2.9.0.20240906 - types-python-dateutil==2.9.0.20240906
- SQLAlchemy==2.0.34 - SQLAlchemy==2.0.34

View File

@ -3594,7 +3594,7 @@ class Exchange:
Wherein, "+" or "-" depends on whether the contract goes long or short: Wherein, "+" or "-" depends on whether the contract goes long or short:
"-" for long, and "+" for short. "-" for long, and "+" for short.
okex: https://www.okex.com/support/hc/en-us/articles/ okex: https://www.okx.com/support/hc/en-us/articles/
360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin 360053909592-VI-Introduction-to-the-isolated-mode-of-Single-Multi-currency-Portfolio-margin
:param pair: Pair to calculate liquidation price for :param pair: Pair to calculate liquidation price for

View File

@ -715,8 +715,6 @@ class FreqtradeBot(LoggingMixin):
""" """
# Walk through each pair and check if it needs changes # Walk through each pair and check if it needs changes
for trade in Trade.get_open_trades(): for trade in Trade.get_open_trades():
# If there is any open orders, wait for them to finish.
# TODO Remove to allow mul open orders
if not trade.has_open_orders: if not trade.has_open_orders:
# Do a wallets update (will be ratelimited to once per hour) # Do a wallets update (will be ratelimited to once per hour)
self.wallets.update(False) self.wallets.update(False)
@ -724,8 +722,7 @@ class FreqtradeBot(LoggingMixin):
self.check_and_call_adjust_trade_position(trade) self.check_and_call_adjust_trade_position(trade)
except DependencyException as exception: except DependencyException as exception:
logger.warning( logger.warning(
f"Unable to adjust position of trade for {trade.pair}: {exception}" f"Unable to adjust position of trade for {trade.pair}: {exception}")
)
def check_and_call_adjust_trade_position(self, trade: Trade): def check_and_call_adjust_trade_position(self, trade: Trade):
""" """
@ -1251,8 +1248,7 @@ class FreqtradeBot(LoggingMixin):
trades_closed = 0 trades_closed = 0
for trade in trades: for trade in trades:
if ( if (
not trade.has_open_orders not trade.has_open_sl_orders
and not trade.has_open_sl_orders
and not self.wallets.check_exit_amount(trade) and not self.wallets.check_exit_amount(trade)
): ):
logger.warning( logger.warning(
@ -1277,7 +1273,7 @@ class FreqtradeBot(LoggingMixin):
f"Unable to handle stoploss on exchange for {trade.pair}: {exception}" f"Unable to handle stoploss on exchange for {trade.pair}: {exception}"
) )
# Check if we can sell our current pair # Check if we can sell our current pair
if not trade.has_open_orders and trade.is_open and self.handle_trade(trade): if trade.is_open and self.handle_trade(trade):
trades_closed += 1 trades_closed += 1
except DependencyException as exception: except DependencyException as exception:
@ -1421,7 +1417,7 @@ class FreqtradeBot(LoggingMixin):
self.handle_protections(trade.pair, trade.trade_direction) self.handle_protections(trade.pair, trade.trade_direction)
return True return True
if trade.has_open_orders or not trade.is_open: if not trade.is_open:
# Trade has an open order, Stoploss-handling can't happen in this case # Trade has an open order, Stoploss-handling can't happen in this case
# as the Amount on the exchange is tied up in another trade. # as the Amount on the exchange is tied up in another trade.
# The trade can be closed already (sell-order fill confirmation came in this iteration) # The trade can be closed already (sell-order fill confirmation came in this iteration)
@ -1689,6 +1685,34 @@ class FreqtradeBot(LoggingMixin):
logger.warning(f"Unable to replace order for {trade.pair}: {exception}") logger.warning(f"Unable to replace order for {trade.pair}: {exception}")
self.replace_order_failed(trade, f"Could not replace order for {trade}.") self.replace_order_failed(trade, f"Could not replace order for {trade}.")
def cancel_open_orders_of_trade(self, trade: Trade, reason: str, sides: List[str]) -> None:
"""
Cancel trade orders of specified sides that are currently open
:param trade: Trade object of the trade we're analyzing
:param reason: The reason for that cancelation
:param sides: The sides where cancellation should take place
:return: None
"""
for open_order in trade.open_orders:
try:
order = self.exchange.fetch_order(open_order.order_id, trade.pair)
except ExchangeError:
logger.info("Can't query order for %s due to %s", trade, traceback.format_exc())
continue
for side in sides:
if (order["side"] == side):
if order["side"] == trade.entry_side:
self.handle_cancel_enter(
trade, order, open_order, reason
)
elif order["side"] == trade.exit_side:
self.handle_cancel_exit(
trade, order, open_order, reason
)
def cancel_all_open_orders(self) -> None: def cancel_all_open_orders(self) -> None:
""" """
Cancel all orders that are currently open Cancel all orders that are currently open
@ -1696,22 +1720,11 @@ class FreqtradeBot(LoggingMixin):
""" """
for trade in Trade.get_open_trades(): for trade in Trade.get_open_trades():
for open_order in trade.open_orders: self.cancel_open_orders_of_trade(
try: trade, constants.CANCEL_REASON["ALL_CANCELLED"],
order = self.exchange.fetch_order(open_order.order_id, trade.pair) [trade.entry_side, trade.exit_side]
except ExchangeError: )
logger.info("Can't query order for %s due to %s", trade, traceback.format_exc())
continue
if order["side"] == trade.entry_side:
self.handle_cancel_enter(
trade, order, open_order, constants.CANCEL_REASON["ALL_CANCELLED"]
)
elif order["side"] == trade.exit_side:
self.handle_cancel_exit(
trade, order, open_order, constants.CANCEL_REASON["ALL_CANCELLED"]
)
Trade.commit() Trade.commit()
def handle_cancel_enter( def handle_cancel_enter(
@ -1957,6 +1970,14 @@ class FreqtradeBot(LoggingMixin):
limit = self.get_valid_price(custom_exit_price, proposed_limit_rate) limit = self.get_valid_price(custom_exit_price, proposed_limit_rate)
if trade.has_open_orders:
# cancel any open order of this trade
self.cancel_open_orders_of_trade(
trade, constants.CANCEL_REASON["REPLACE"],
[trade.exit_side]
)
Trade.commit()
# First cancelling stoploss on exchange ... # First cancelling stoploss on exchange ...
trade = self.cancel_stoploss_on_exchange(trade) trade = self.cancel_stoploss_on_exchange(trade)

View File

@ -1376,8 +1376,7 @@ class Backtesting:
self.wallets.update() self.wallets.update()
# 4. Create exit orders (if any) # 4. Create exit orders (if any)
if not trade.has_open_orders: self._check_trade_exit(trade, row, current_time) # Place exit order if necessary
self._check_trade_exit(trade, row, current_time) # Place exit order if necessary
# 5. Process exit orders. # 5. Process exit orders.
order = trade.select_order(trade.exit_side, is_open=True) order = trade.select_order(trade.exit_side, is_open=True)

View File

@ -178,6 +178,7 @@ class Order(ModelBase):
return ( return (
f"Order(id={self.id}, trade={self.ft_trade_id}, order_id={self.order_id}, " f"Order(id={self.id}, trade={self.ft_trade_id}, order_id={self.order_id}, "
f"side={self.side}, filled={self.safe_filled}, price={self.safe_price}, " f"side={self.side}, filled={self.safe_filled}, price={self.safe_price}, "
f"amount={self.amount}, "
f"status={self.status}, date={self.order_date_utc:{DATETIME_PRINT_FORMAT}})" f"status={self.status}, date={self.order_date_utc:{DATETIME_PRINT_FORMAT}})"
) )
@ -585,6 +586,67 @@ class LocalTrade:
] ]
return len(open_orders_wo_sl) > 0 return len(open_orders_wo_sl) > 0
@property
def has_open_entry_orders(self) -> bool:
"""
True if there are open entry orders for this trade
"""
open_entry_orders = [
o for o in self.orders
if o.ft_order_side == self.entry_side and o.ft_is_open
]
return len(open_entry_orders) > 0
@property
def has_open_position(self) -> bool:
"""
True if there is an open position for this trade
"""
entry_orders = [
o for o in self.orders
if o.ft_order_side == self.entry_side
]
entry_orders_filled_qty = sum(eno.safe_filled for eno in entry_orders)
exit_orders = [
o for o in self.orders
if o.ft_order_side == self.exit_side
]
exit_orders_filled_qty = sum(exo.safe_filled for exo in exit_orders)
return (entry_orders_filled_qty - exit_orders_filled_qty) > 0
@property
def untied_assets(self) -> float:
entry_orders = [
o for o in self.orders
if o.ft_order_side == self.entry_side
]
entry_orders_filled_qty = sum(eno.safe_filled for eno in entry_orders)
exit_orders = [
o for o in self.orders
if o.ft_order_side == self.exit_side
]
exit_orders_remaining_qty = sum(exo.safe_remaining for exo in exit_orders)
untied_remaining = entry_orders_filled_qty - exit_orders_remaining_qty
logger.info(f"entry_orders: {entry_orders}")
logger.info(f"exit_orders: {exit_orders}")
logger.info(f"entry_orders_filled_qty: {entry_orders_filled_qty}")
logger.info(f"exit_orders_remaining_qty: {exit_orders_remaining_qty}")
logger.info(f"untied_remaining: {untied_remaining}")
return untied_remaining
@property
def has_untied_assets(self) -> bool:
"""
True if there is still remaining position not yet tied up to exit order
"""
return self.untied_assets > 0
@property @property
def open_sl_orders(self) -> List[Order]: def open_sl_orders(self) -> List[Order]:
""" """

View File

@ -7,10 +7,10 @@
-r docs/requirements-docs.txt -r docs/requirements-docs.txt
coveralls==4.0.1 coveralls==4.0.1
ruff==0.6.4 ruff==0.6.5
mypy==1.11.2 mypy==1.11.2
pre-commit==3.8.0 pre-commit==3.8.0
pytest==8.3.2 pytest==8.3.3
pytest-asyncio==0.24.0 pytest-asyncio==0.24.0
pytest-cov==5.0.0 pytest-cov==5.0.0
pytest-mock==3.14.0 pytest-mock==3.14.0
@ -27,6 +27,6 @@ nbconvert==7.16.4
# mypy types # mypy types
types-cachetools==5.5.0.20240820 types-cachetools==5.5.0.20240820
types-filelock==3.2.7 types-filelock==3.2.7
types-requests==2.32.0.20240907 types-requests==2.32.0.20240914
types-tabulate==0.9.0.20240106 types-tabulate==0.9.0.20240106
types-python-dateutil==2.9.0.20240906 types-python-dateutil==2.9.0.20240906

View File

@ -3,7 +3,7 @@
-r requirements-plot.txt -r requirements-plot.txt
# Required for freqai # Required for freqai
scikit-learn==1.5.1 scikit-learn==1.5.2
joblib==1.4.2 joblib==1.4.2
catboost==1.2.7; 'arm' not in platform_machine catboost==1.2.7; 'arm' not in platform_machine
# Pin Matplotlib - it's depended on by catboost # Pin Matplotlib - it's depended on by catboost

View File

@ -4,6 +4,6 @@
# Required for hyperopt # Required for hyperopt
scipy==1.14.1; python_version >= "3.10" scipy==1.14.1; python_version >= "3.10"
scipy==1.13.1; python_version < "3.10" scipy==1.13.1; python_version < "3.10"
scikit-learn==1.5.1 scikit-learn==1.5.2
ft-scikit-optimize==0.9.2 ft-scikit-optimize==0.9.2
filelock==3.16.0 filelock==3.16.0

View File

@ -1,4 +1,4 @@
# Include all requirements to run the bot. # Include all requirements to run the bot.
-r requirements.txt -r requirements.txt
plotly==5.24.0 plotly==5.24.1

View File

@ -4,7 +4,7 @@ bottleneck==1.4.0
numexpr==2.10.1 numexpr==2.10.1
pandas-ta==0.3.14b pandas-ta==0.3.14b
ccxt==4.3.98 ccxt==4.4.3
cryptography==42.0.8; platform_machine == 'armv7l' cryptography==42.0.8; platform_machine == 'armv7l'
cryptography==43.0.1; platform_machine != 'armv7l' cryptography==43.0.1; platform_machine != 'armv7l'
aiohttp==3.10.5 aiohttp==3.10.5
@ -15,7 +15,7 @@ httpx>=0.24.1
humanize==4.10.0 humanize==4.10.0
cachetools==5.5.0 cachetools==5.5.0
requests==2.32.3 requests==2.32.3
urllib3==2.2.2 urllib3==2.2.3
jsonschema==4.23.0 jsonschema==4.23.0
TA-Lib==0.4.32 TA-Lib==0.4.32
technical==1.4.4 technical==1.4.4
@ -26,7 +26,7 @@ jinja2==3.1.4
tables==3.9.1; python_version < "3.10" tables==3.9.1; python_version < "3.10"
tables==3.10.1; python_version >= "3.10" tables==3.10.1; python_version >= "3.10"
joblib==1.4.2 joblib==1.4.2
rich==13.8.0 rich==13.8.1
pyarrow==17.0.0; platform_machine != 'armv7l' pyarrow==17.0.0; platform_machine != 'armv7l'
# find first, C search in arrays # find first, C search in arrays
@ -41,8 +41,8 @@ orjson==3.10.7
sdnotify==0.3.2 sdnotify==0.3.2
# API Server # API Server
fastapi==0.114.0 fastapi==0.114.2
pydantic==2.9.0 pydantic==2.9.1
uvicorn==0.30.6 uvicorn==0.30.6
pyjwt==2.9.0 pyjwt==2.9.0
aiofiles==24.1.0 aiofiles==24.1.0
@ -53,7 +53,7 @@ questionary==2.0.1
prompt-toolkit==3.0.36 prompt-toolkit==3.0.36
# Extensions to datetime library # Extensions to datetime library
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
pytz==2024.1 pytz==2024.2
#Futures #Futures
schedule==1.2.2 schedule==1.2.2

View File

@ -964,6 +964,29 @@ def get_markets():
}, },
"info": {}, "info": {},
}, },
"ETC/BTC": {
"id": "ETCBTC",
"symbol": "ETC/BTC",
"base": "ETC",
"quote": "BTC",
"active": True,
"spot": True,
"swap": False,
"linear": None,
"type": "spot",
"contractSize": None,
"precision": {"base": 8, "quote": 8, "amount": 2, "price": 7},
"limits": {
"amount": {"min": 0.01, "max": 90000000.0},
"price": {"min": 1e-07, "max": 1000.0},
"cost": {"min": 0.0001, "max": 9000000.0},
"leverage": {
"min": None,
"max": None,
},
},
"info": {},
},
"ETH/USDT": { "ETH/USDT": {
"id": "USDT-ETH", "id": "USDT-ETH",
"symbol": "ETH/USDT", "symbol": "ETH/USDT",

View File

@ -1265,14 +1265,14 @@ def test_exit_positions(mocker, default_conf_usdt, limit_order, is_short, caplog
trades = [trade] trades = [trade]
freqtrade.wallets.update() freqtrade.wallets.update()
n = freqtrade.exit_positions(trades) n = freqtrade.exit_positions(trades)
assert n == 0 assert n == 1
# Test amount not modified by fee-logic # Test amount not modified by fee-logic
assert not log_has_re(r"Applying fee to amount for Trade .*", caplog) assert not log_has_re(r"Applying fee to amount for Trade .*", caplog)
gra = mocker.patch("freqtrade.freqtradebot.FreqtradeBot.get_real_amount", return_value=0.0) gra = mocker.patch("freqtrade.freqtradebot.FreqtradeBot.get_real_amount", return_value=0.0)
# test amount modified by fee-logic # test amount modified by fee-logic
n = freqtrade.exit_positions(trades) n = freqtrade.exit_positions(trades)
assert n == 0 assert n == 1
assert gra.call_count == 0 assert gra.call_count == 0
@ -1305,6 +1305,7 @@ def test_exit_positions_exception(mocker, default_conf_usdt, limit_order, caplog
ft_price=trade.open_rate, ft_price=trade.open_rate,
order_id=order_id, order_id=order_id,
ft_is_open=False, ft_is_open=False,
filled=11
) )
) )
Trade.session.add(trade) Trade.session.add(trade)

View File

@ -1,3 +1,4 @@
import logging
import time import time
from unittest.mock import MagicMock from unittest.mock import MagicMock
@ -347,8 +348,8 @@ def test_dca_short(default_conf_usdt, ticker_usdt, fee, mocker) -> None:
assert trade.nr_of_successful_exits == 1 assert trade.nr_of_successful_exits == 1
@pytest.mark.parametrize("leverage", [1, 2]) @pytest.mark.parametrize("leverage", [1])
def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker) -> None: def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker, caplog) -> None:
default_conf_usdt["position_adjustment_enable"] = True default_conf_usdt["position_adjustment_enable"] = True
default_conf_usdt["trading_mode"] = "futures" default_conf_usdt["trading_mode"] = "futures"
default_conf_usdt["margin_mode"] = "isolated" default_conf_usdt["margin_mode"] = "isolated"
@ -478,10 +479,16 @@ def test_dca_order_adjust(default_conf_usdt, ticker_usdt, leverage, fee, mocker)
assert pytest.approx(trade.amount) == 91.689215 * leverage assert pytest.approx(trade.amount) == 91.689215 * leverage
assert pytest.approx(trade.orders[-1].amount) == 91.689215 * leverage assert pytest.approx(trade.orders[-1].amount) == 91.689215 * leverage
assert freqtrade.strategy.adjust_entry_price.call_count == 0 assert freqtrade.strategy.adjust_entry_price.call_count == 0
caplog.clear()
caplog.set_level(logging.DEBUG)
# Process again, should not adjust entry price # Process again, should not adjust entry price
freqtrade.process() freqtrade.process()
trade = Trade.get_trades().first() trade = Trade.get_trades().first()
assert len(trade.orders) == 5
assert trade.orders[-2].status == "canceled"
assert len(trade.orders) == 6
assert trade.orders[-1].side == trade.exit_side
assert trade.orders[-1].status == "open" assert trade.orders[-1].status == "open"
assert trade.orders[-1].price == 2.02 assert trade.orders[-1].price == 2.02
# Adjust entry price cannot be called - this is an exit order # Adjust entry price cannot be called - this is an exit order