Merge branch 'develop' into dependabot/pip/develop/types-python-dateutil-2.8.19.10

pull/8282/head
Matthias 3 years ago committed by GitHub
commit 0d876d7a89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -18,7 +18,7 @@ repos:
- types-requests==2.28.11.15
- types-tabulate==0.9.0.1
- types-python-dateutil==2.8.19.10
- SQLAlchemy==2.0.4
- SQLAlchemy==2.0.5.post1
# stages: [push]
- repo: https://github.com/pycqa/isort

@ -1,6 +1,6 @@
markdown==3.3.7
mkdocs==1.4.2
mkdocs-material==9.0.15
mkdocs-material==9.1.1
mdx_truly_sane_lists==1.3
pymdown-extensions==9.9.2
pymdown-extensions==9.10
jinja2==3.1.2

@ -2,8 +2,7 @@ from datetime import datetime, timezone
from typing import Any, ClassVar, Dict, Optional
from sqlalchemy import String, or_
from sqlalchemy.orm import Mapped, Query, mapped_column
from sqlalchemy.orm.scoping import _QueryDescriptorType
from sqlalchemy.orm import Mapped, Query, QueryPropertyDescriptor, mapped_column
from freqtrade.constants import DATETIME_PRINT_FORMAT
from freqtrade.persistence.base import ModelBase, SessionType
@ -14,7 +13,7 @@ class PairLock(ModelBase):
Pair Locks database model.
"""
__tablename__ = 'pairlocks'
query: ClassVar[_QueryDescriptorType]
query: ClassVar[QueryPropertyDescriptor]
_session: ClassVar[SessionType]
id: Mapped[int] = mapped_column(primary_key=True)

@ -8,8 +8,8 @@ from math import isclose
from typing import Any, ClassVar, Dict, List, Optional, cast
from sqlalchemy import Enum, Float, ForeignKey, Integer, String, UniqueConstraint, desc, func
from sqlalchemy.orm import Mapped, Query, lazyload, mapped_column, relationship
from sqlalchemy.orm.scoping import _QueryDescriptorType
from sqlalchemy.orm import (Mapped, Query, QueryPropertyDescriptor, lazyload, mapped_column,
relationship)
from freqtrade.constants import (DATETIME_PRINT_FORMAT, MATH_CLOSE_PREC, NON_OPEN_EXCHANGE_STATES,
BuySell, LongShort)
@ -36,7 +36,7 @@ class Order(ModelBase):
Mirrors CCXT Order structure
"""
__tablename__ = 'orders'
query: ClassVar[_QueryDescriptorType]
query: ClassVar[QueryPropertyDescriptor]
_session: ClassVar[SessionType]
# Uniqueness should be ensured over pair, order_id
@ -1181,7 +1181,7 @@ class Trade(ModelBase, LocalTrade):
Note: Fields must be aligned with LocalTrade class
"""
__tablename__ = 'trades'
query: ClassVar[_QueryDescriptorType]
query: ClassVar[QueryPropertyDescriptor]
_session: ClassVar[SessionType]
use_db: bool = True

@ -286,6 +286,7 @@ class OpenTradeSchema(TradeSchema):
current_rate: float
total_profit_abs: float
total_profit_fiat: Optional[float]
total_profit_ratio: Optional[float]
open_order: Optional[str]

@ -42,7 +42,8 @@ logger = logging.getLogger(__name__)
# 2.22: Add FreqAI to backtesting
# 2.23: Allow plot config request in webserver mode
# 2.24: Add cancel_open_order endpoint
API_VERSION = 2.24
# 2.25: Add several profit values to /status endpoint
API_VERSION = 2.25
# Public API, requires no auth.
router_public = APIRouter()

@ -192,6 +192,11 @@ class RPC:
current_profit = trade.close_profit or 0.0
current_profit_abs = trade.close_profit_abs or 0.0
total_profit_abs = trade.realized_profit + current_profit_abs
total_profit_ratio: Optional[float] = None
if trade.max_stake_amount:
total_profit_ratio = (
(total_profit_abs / trade.max_stake_amount) * trade.leverage
)
# Calculate fiat profit
if not isnan(current_profit_abs) and self._fiat_converter:
@ -224,6 +229,7 @@ class RPC:
total_profit_abs=total_profit_abs,
total_profit_fiat=total_profit_fiat,
total_profit_ratio=total_profit_ratio,
stoploss_current_dist=stoploss_current_dist,
stoploss_current_dist_ratio=round(stoploss_current_dist_ratio, 8),
stoploss_current_dist_pct=round(stoploss_current_dist_ratio * 100, 2),

@ -510,14 +510,14 @@ class Telegram(RPCHandler):
if prev_avg_price:
minus_on_entry = (cur_entry_average - prev_avg_price) / prev_avg_price
lines.append(f"*{wording} #{order_nr}:* at {minus_on_entry:.2%} avg profit")
lines.append(f"*{wording} #{order_nr}:* at {minus_on_entry:.2%} avg Profit")
if is_open:
lines.append("({})".format(cur_entry_datetime
.humanize(granularity=["day", "hour", "minute"])))
lines.append(f"*Amount:* {cur_entry_amount} "
f"({round_coin_value(order['cost'], quote_currency)})")
lines.append(f"*Average {wording} Price:* {cur_entry_average} "
f"({price_to_1st_entry:.2%} from 1st entry rate)")
f"({price_to_1st_entry:.2%} from 1st entry Rate)")
lines.append(f"*Order filled:* {order['order_filled_date']}")
# TODO: is this really useful?
@ -569,6 +569,8 @@ class Telegram(RPCHandler):
and not o['ft_order_side'] == 'stoploss'])
r['exit_reason'] = r.get('exit_reason', "")
r['stake_amount_r'] = round_coin_value(r['stake_amount'], r['quote_currency'])
r['max_stake_amount_r'] = round_coin_value(
r['max_stake_amount'] or r['stake_amount'], r['quote_currency'])
r['profit_abs_r'] = round_coin_value(r['profit_abs'], r['quote_currency'])
r['realized_profit_r'] = round_coin_value(r['realized_profit'], r['quote_currency'])
r['total_profit_abs_r'] = round_coin_value(
@ -580,31 +582,37 @@ class Telegram(RPCHandler):
f"*Direction:* {'`Short`' if r.get('is_short') else '`Long`'}"
+ " ` ({leverage}x)`" if r.get('leverage') else "",
"*Amount:* `{amount} ({stake_amount_r})`",
"*Total invested:* `{max_stake_amount_r}`" if position_adjust else "",
"*Enter Tag:* `{enter_tag}`" if r['enter_tag'] else "",
"*Exit Reason:* `{exit_reason}`" if r['exit_reason'] else "",
]
if position_adjust:
max_buy_str = (f"/{max_entries + 1}" if (max_entries > 0) else "")
lines.append("*Number of Entries:* `{num_entries}" + max_buy_str + "`")
lines.append("*Number of Exits:* `{num_exits}`")
lines.extend([
"*Number of Entries:* `{num_entries}" + max_buy_str + "`",
"*Number of Exits:* `{num_exits}`"
])
lines.extend([
"*Open Rate:* `{open_rate:.8f}`",
"*Close Rate:* `{close_rate:.8f}`" if r['close_rate'] else "",
"*Open Date:* `{open_date}`",
"*Close Date:* `{close_date}`" if r['close_date'] else "",
"*Current Rate:* `{current_rate:.8f}`" if r['is_open'] else "",
" \n*Current Rate:* `{current_rate:.8f}`" if r['is_open'] else "",
("*Unrealized Profit:* " if r['is_open'] else "*Close Profit: *")
+ "`{profit_ratio:.2%}` `({profit_abs_r})`",
])
if r['is_open']:
if r.get('realized_profit'):
lines.append(
"*Realized Profit:* `{realized_profit_r} {realized_profit_ratio:.2%}`")
lines.append("*Total Profit:* `{total_profit_abs_r}` ")
lines.extend([
"*Realized Profit:* `{realized_profit_ratio:.2%} ({realized_profit_r})`",
"*Total Profit:* `{total_profit_ratio:.2%} ({total_profit_abs_r})`"
])
# Append empty line to improve readability
lines.append(" ")
if (r['stop_loss_abs'] != r['initial_stop_loss_abs']
and r['initial_stop_loss_ratio'] is not None):
# Adding initial stoploss only if it is different from stoploss

@ -7,7 +7,7 @@
-r docs/requirements-docs.txt
coveralls==3.3.1
ruff==0.0.253
ruff==0.0.254
mypy==1.0.1
pre-commit==3.1.1
pytest==7.2.1

@ -3,9 +3,9 @@ pandas==1.5.3
pandas-ta==0.3.14b
ccxt==2.8.98
cryptography==39.0.1
cryptography==39.0.2
aiohttp==3.8.4
SQLAlchemy==2.0.4
SQLAlchemy==2.0.5.post1
python-telegram-bot==13.15
arrow==1.2.3
cachetools==4.2.2
@ -28,7 +28,7 @@ py_find_1st==1.1.5
# Load ticker files 30% faster
python-rapidjson==1.9
# Properly format api responses
orjson==3.8.6
orjson==3.8.7
# Notify systemd
sdnotify==0.3.2
@ -45,7 +45,7 @@ psutil==5.9.4
colorama==0.4.6
# Building config files interactively
questionary==1.10.0
prompt-toolkit==3.0.37
prompt-toolkit==3.0.38
# Extensions to datetime library
python-dateutil==2.8.2

@ -50,7 +50,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'amount': 91.07468123,
'amount_requested': 91.07468124,
'stake_amount': 0.001,
'max_stake_amount': ANY,
'max_stake_amount': None,
'trade_duration': None,
'trade_duration_s': None,
'close_profit': None,
@ -79,6 +79,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'realized_profit_ratio': None,
'total_profit_abs': -4.09e-06,
'total_profit_fiat': ANY,
'total_profit_ratio': None,
'exchange': 'binance',
'leverage': 1.0,
'interest_rate': 0.0,
@ -168,6 +169,10 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
results = rpc._rpc_trade_status()
response = deepcopy(gen_response)
response.update({
'max_stake_amount': 0.001,
'total_profit_ratio': pytest.approx(-0.00409),
})
assert results[0] == response
mocker.patch(f'{EXMS}.get_rate',
@ -181,10 +186,12 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'stoploss_current_dist': ANY,
'stoploss_current_dist_ratio': ANY,
'stoploss_current_dist_pct': ANY,
'max_stake_amount': 0.001,
'profit_ratio': ANY,
'profit_pct': ANY,
'profit_abs': ANY,
'total_profit_abs': ANY,
'total_profit_ratio': ANY,
'current_rate': ANY,
})
assert results[0] == response_norate

@ -1012,6 +1012,7 @@ def test_api_status(botclient, mocker, ticker, fee, markets, is_short,
'profit_fiat': ANY,
'total_profit_abs': ANY,
'total_profit_fiat': ANY,
'total_profit_ratio': ANY,
'realized_profit': 0.0,
'realized_profit_ratio': None,
'current_rate': current_rate,

@ -198,6 +198,7 @@ def test_telegram_status(default_conf, update, mocker) -> None:
'current_rate': 1.098e-05,
'amount': 90.99181074,
'stake_amount': 90.99181074,
'max_stake_amount': 90.99181074,
'buy_tag': None,
'enter_tag': None,
'close_profit_ratio': None,

Loading…
Cancel
Save