Merge pull request #8379 from xmatthias/type_sendmsg

Type sendmsg
This commit is contained in:
Matthias
2023-03-26 14:09:01 +02:00
committed by GitHub
9 changed files with 172 additions and 26 deletions

View File

@@ -13,6 +13,7 @@ from freqtrade.exceptions import OperationalException
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
from freqtrade.rpc.api_server.ws.message_stream import MessageStream
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
from freqtrade.rpc.rpc_types import RPCSendMsg
logger = logging.getLogger(__name__)
@@ -108,7 +109,7 @@ class ApiServer(RPCHandler):
cls._has_rpc = False
cls._rpc = None
def send_msg(self, msg: Dict[str, Any]) -> None:
def send_msg(self, msg: RPCSendMsg) -> None:
"""
Publish the message to the message stream
"""

View File

@@ -30,6 +30,7 @@ from freqtrade.persistence import Order, PairLocks, Trade
from freqtrade.persistence.models import PairLock
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
from freqtrade.rpc.rpc_types import RPCSendMsg
from freqtrade.wallets import PositionWallet, Wallet
@@ -79,7 +80,7 @@ class RPCHandler:
""" Cleanup pending module resources """
@abstractmethod
def send_msg(self, msg: Dict[str, str]) -> None:
def send_msg(self, msg: RPCSendMsg) -> None:
""" Sends a message to all registered rpc modules """

View File

@@ -3,11 +3,12 @@ This module contains class to manage RPC communications (Telegram, API, ...)
"""
import logging
from collections import deque
from typing import Any, Dict, List
from typing import List
from freqtrade.constants import Config
from freqtrade.enums import NO_ECHO_MESSAGES, RPCMessageType
from freqtrade.rpc import RPC, RPCHandler
from freqtrade.rpc.rpc_types import RPCSendMsg
logger = logging.getLogger(__name__)
@@ -58,7 +59,7 @@ class RPCManager:
mod.cleanup()
del mod
def send_msg(self, msg: Dict[str, Any]) -> None:
def send_msg(self, msg: RPCSendMsg) -> None:
"""
Send given message to all registered rpc modules.
A message consists of one or more key value pairs of strings.
@@ -69,10 +70,6 @@ class RPCManager:
"""
if msg.get('type') not in NO_ECHO_MESSAGES:
logger.info('Sending rpc message: %s', msg)
if 'pair' in msg:
msg.update({
'base_currency': self._rpc._freqtrade.exchange.get_pair_base_currency(msg['pair'])
})
for mod in self.registered_modules:
logger.debug('Forwarding message to rpc.%s', mod.name)
try:

128
freqtrade/rpc/rpc_types.py Normal file
View File

@@ -0,0 +1,128 @@
from datetime import datetime
from typing import Any, List, Literal, Optional, TypedDict, Union
from freqtrade.constants import PairWithTimeframe
from freqtrade.enums import RPCMessageType
class RPCSendMsgBase(TypedDict):
pass
# ty1pe: Literal[RPCMessageType]
class RPCStatusMsg(RPCSendMsgBase):
"""Used for Status, Startup and Warning messages"""
type: Literal[RPCMessageType.STATUS, RPCMessageType.STARTUP, RPCMessageType.WARNING]
status: str
class RPCStrategyMsg(RPCSendMsgBase):
"""Used for Status, Startup and Warning messages"""
type: Literal[RPCMessageType.STRATEGY_MSG]
msg: str
class RPCProtectionMsg(RPCSendMsgBase):
type: Literal[RPCMessageType.PROTECTION_TRIGGER, RPCMessageType.PROTECTION_TRIGGER_GLOBAL]
id: int
pair: str
base_currency: Optional[str]
lock_time: str
lock_timestamp: int
lock_end_time: str
lock_end_timestamp: int
reason: str
side: str
active: bool
class RPCWhitelistMsg(RPCSendMsgBase):
type: Literal[RPCMessageType.WHITELIST]
data: List[str]
class __RPCBuyMsgBase(RPCSendMsgBase):
trade_id: int
buy_tag: Optional[str]
enter_tag: Optional[str]
exchange: str
pair: str
base_currency: str
leverage: Optional[float]
direction: str
limit: float
open_rate: float
order_type: Optional[str] # TODO: why optional??
stake_amount: float
stake_currency: str
fiat_currency: Optional[str]
amount: float
open_date: datetime
current_rate: Optional[float]
sub_trade: bool
class RPCBuyMsg(__RPCBuyMsgBase):
type: Literal[RPCMessageType.ENTRY, RPCMessageType.ENTRY_FILL]
class RPCCancelMsg(__RPCBuyMsgBase):
type: Literal[RPCMessageType.ENTRY_CANCEL]
reason: str
class RPCSellMsg(__RPCBuyMsgBase):
type: Literal[RPCMessageType.EXIT, RPCMessageType.EXIT_FILL]
cumulative_profit: float
gain: str # Literal["profit", "loss"]
close_rate: float
profit_amount: float
profit_ratio: float
sell_reason: Optional[str]
exit_reason: Optional[str]
close_date: datetime
# current_rate: Optional[float]
order_rate: Optional[float]
class RPCSellCancelMsg(__RPCBuyMsgBase):
type: Literal[RPCMessageType.EXIT_CANCEL]
reason: str
gain: str # Literal["profit", "loss"]
profit_amount: float
profit_ratio: float
sell_reason: Optional[str]
exit_reason: Optional[str]
close_date: datetime
class _AnalyzedDFData(TypedDict):
key: PairWithTimeframe
df: Any
la: datetime
class RPCAnalyzedDFMsg(RPCSendMsgBase):
"""New Analyzed dataframe message"""
type: Literal[RPCMessageType.ANALYZED_DF]
data: _AnalyzedDFData
class RPCNewCandleMsg(RPCSendMsgBase):
"""New candle ping message, issued once per new candle/pair"""
type: Literal[RPCMessageType.NEW_CANDLE]
data: PairWithTimeframe
RPCSendMsg = Union[
RPCStatusMsg,
RPCStrategyMsg,
RPCProtectionMsg,
RPCWhitelistMsg,
RPCBuyMsg,
RPCCancelMsg,
RPCSellMsg,
RPCSellCancelMsg,
RPCAnalyzedDFMsg,
RPCNewCandleMsg
]

View File

@@ -30,6 +30,7 @@ from freqtrade.exceptions import OperationalException
from freqtrade.misc import chunks, plural, round_coin_value
from freqtrade.persistence import Trade
from freqtrade.rpc import RPC, RPCException, RPCHandler
from freqtrade.rpc.rpc_types import RPCSendMsg
logger = logging.getLogger(__name__)
@@ -429,14 +430,14 @@ class Telegram(RPCHandler):
return None
return message
def send_msg(self, msg: Dict[str, Any]) -> None:
def send_msg(self, msg: RPCSendMsg) -> None:
""" Send a message to telegram channel """
default_noti = 'on'
msg_type = msg['type']
noti = ''
if msg_type == RPCMessageType.EXIT:
if msg['type'] == RPCMessageType.EXIT:
sell_noti = self._config['telegram'] \
.get('notification_settings', {}).get(str(msg_type), {})
# For backward compatibility sell still can be string
@@ -453,7 +454,7 @@ class Telegram(RPCHandler):
# Notification disabled
return
message = self.compose_message(deepcopy(msg), msg_type)
message = self.compose_message(deepcopy(msg), msg_type) # type: ignore
if message:
self._send_msg(message, disable_notification=(noti == 'silent'))

View File

@@ -10,6 +10,7 @@ from requests import RequestException, post
from freqtrade.constants import Config
from freqtrade.enums import RPCMessageType
from freqtrade.rpc import RPC, RPCHandler
from freqtrade.rpc.rpc_types import RPCSendMsg
logger = logging.getLogger(__name__)
@@ -41,7 +42,7 @@ class Webhook(RPCHandler):
"""
pass
def _get_value_dict(self, msg: Dict[str, Any]) -> Optional[Dict[str, Any]]:
def _get_value_dict(self, msg: RPCSendMsg) -> Optional[Dict[str, Any]]:
whconfig = self._config['webhook']
# Deprecated 2022.10 - only keep generic method.
if msg['type'] in [RPCMessageType.ENTRY]:
@@ -75,7 +76,7 @@ class Webhook(RPCHandler):
return None
return valuedict
def send_msg(self, msg: Dict[str, Any]) -> None:
def send_msg(self, msg: RPCSendMsg) -> None:
""" Send a message to telegram channel """
try: