commit
d97500581d
@ -21,6 +21,7 @@ from freqtrade.exchange import Exchange, timeframe_to_seconds
|
|||||||
from freqtrade.exchange.types import OrderBook
|
from freqtrade.exchange.types import OrderBook
|
||||||
from freqtrade.misc import append_candles_to_dataframe
|
from freqtrade.misc import append_candles_to_dataframe
|
||||||
from freqtrade.rpc import RPCManager
|
from freqtrade.rpc import RPCManager
|
||||||
|
from freqtrade.rpc.rpc_types import RPCAnalyzedDFMsg
|
||||||
from freqtrade.util import PeriodicCache
|
from freqtrade.util import PeriodicCache
|
||||||
|
|
||||||
|
|
||||||
@ -118,8 +119,7 @@ class DataProvider:
|
|||||||
:param new_candle: This is a new candle
|
:param new_candle: This is a new candle
|
||||||
"""
|
"""
|
||||||
if self.__rpc:
|
if self.__rpc:
|
||||||
self.__rpc.send_msg(
|
msg: RPCAnalyzedDFMsg = {
|
||||||
{
|
|
||||||
'type': RPCMessageType.ANALYZED_DF,
|
'type': RPCMessageType.ANALYZED_DF,
|
||||||
'data': {
|
'data': {
|
||||||
'key': pair_key,
|
'key': pair_key,
|
||||||
@ -127,7 +127,7 @@ class DataProvider:
|
|||||||
'la': datetime.now(timezone.utc)
|
'la': datetime.now(timezone.utc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
self.__rpc.send_msg(msg)
|
||||||
if new_candle:
|
if new_candle:
|
||||||
self.__rpc.send_msg({
|
self.__rpc.send_msg({
|
||||||
'type': RPCMessageType.NEW_CANDLE,
|
'type': RPCMessageType.NEW_CANDLE,
|
||||||
|
@ -30,6 +30,8 @@ from freqtrade.plugins.protectionmanager import ProtectionManager
|
|||||||
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
|
||||||
from freqtrade.rpc import RPCManager
|
from freqtrade.rpc import RPCManager
|
||||||
from freqtrade.rpc.external_message_consumer import ExternalMessageConsumer
|
from freqtrade.rpc.external_message_consumer import ExternalMessageConsumer
|
||||||
|
from freqtrade.rpc.rpc_types import (RPCBuyMsg, RPCCancelMsg, RPCProtectionMsg, RPCSellCancelMsg,
|
||||||
|
RPCSellMsg)
|
||||||
from freqtrade.strategy.interface import IStrategy
|
from freqtrade.strategy.interface import IStrategy
|
||||||
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
from freqtrade.strategy.strategy_wrapper import strategy_safe_wrapper
|
||||||
from freqtrade.util import FtPrecise
|
from freqtrade.util import FtPrecise
|
||||||
@ -948,7 +950,6 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
"""
|
"""
|
||||||
Sends rpc notification when a entry order occurred.
|
Sends rpc notification when a entry order occurred.
|
||||||
"""
|
"""
|
||||||
msg_type = RPCMessageType.ENTRY_FILL if fill else RPCMessageType.ENTRY
|
|
||||||
open_rate = order.safe_price
|
open_rate = order.safe_price
|
||||||
|
|
||||||
if open_rate is None:
|
if open_rate is None:
|
||||||
@ -959,9 +960,9 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
current_rate = self.exchange.get_rate(
|
current_rate = self.exchange.get_rate(
|
||||||
trade.pair, side='entry', is_short=trade.is_short, refresh=False)
|
trade.pair, side='entry', is_short=trade.is_short, refresh=False)
|
||||||
|
|
||||||
msg = {
|
msg: RPCBuyMsg = {
|
||||||
'trade_id': trade.id,
|
'trade_id': trade.id,
|
||||||
'type': msg_type,
|
'type': RPCMessageType.ENTRY_FILL if fill else RPCMessageType.ENTRY,
|
||||||
'buy_tag': trade.enter_tag,
|
'buy_tag': trade.enter_tag,
|
||||||
'enter_tag': trade.enter_tag,
|
'enter_tag': trade.enter_tag,
|
||||||
'exchange': trade.exchange.capitalize(),
|
'exchange': trade.exchange.capitalize(),
|
||||||
@ -973,6 +974,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'order_type': order_type,
|
'order_type': order_type,
|
||||||
'stake_amount': trade.stake_amount,
|
'stake_amount': trade.stake_amount,
|
||||||
'stake_currency': self.config['stake_currency'],
|
'stake_currency': self.config['stake_currency'],
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
'fiat_currency': self.config.get('fiat_display_currency', None),
|
'fiat_currency': self.config.get('fiat_display_currency', None),
|
||||||
'amount': order.safe_amount_after_fee if fill else (order.amount or trade.amount),
|
'amount': order.safe_amount_after_fee if fill else (order.amount or trade.amount),
|
||||||
'open_date': trade.open_date or datetime.utcnow(),
|
'open_date': trade.open_date or datetime.utcnow(),
|
||||||
@ -991,7 +993,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
current_rate = self.exchange.get_rate(
|
current_rate = self.exchange.get_rate(
|
||||||
trade.pair, side='entry', is_short=trade.is_short, refresh=False)
|
trade.pair, side='entry', is_short=trade.is_short, refresh=False)
|
||||||
|
|
||||||
msg = {
|
msg: RPCCancelMsg = {
|
||||||
'trade_id': trade.id,
|
'trade_id': trade.id,
|
||||||
'type': RPCMessageType.ENTRY_CANCEL,
|
'type': RPCMessageType.ENTRY_CANCEL,
|
||||||
'buy_tag': trade.enter_tag,
|
'buy_tag': trade.enter_tag,
|
||||||
@ -1003,7 +1005,9 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'limit': trade.open_rate,
|
'limit': trade.open_rate,
|
||||||
'order_type': order_type,
|
'order_type': order_type,
|
||||||
'stake_amount': trade.stake_amount,
|
'stake_amount': trade.stake_amount,
|
||||||
|
'open_rate': trade.open_rate,
|
||||||
'stake_currency': self.config['stake_currency'],
|
'stake_currency': self.config['stake_currency'],
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
'fiat_currency': self.config.get('fiat_display_currency', None),
|
'fiat_currency': self.config.get('fiat_display_currency', None),
|
||||||
'amount': trade.amount,
|
'amount': trade.amount,
|
||||||
'open_date': trade.open_date,
|
'open_date': trade.open_date,
|
||||||
@ -1663,7 +1667,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
amount = trade.amount
|
amount = trade.amount
|
||||||
gain = "profit" if profit_ratio > 0 else "loss"
|
gain = "profit" if profit_ratio > 0 else "loss"
|
||||||
|
|
||||||
msg = {
|
msg: RPCSellMsg = {
|
||||||
'type': (RPCMessageType.EXIT_FILL if fill
|
'type': (RPCMessageType.EXIT_FILL if fill
|
||||||
else RPCMessageType.EXIT),
|
else RPCMessageType.EXIT),
|
||||||
'trade_id': trade.id,
|
'trade_id': trade.id,
|
||||||
@ -1689,6 +1693,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'close_date': trade.close_date or datetime.utcnow(),
|
'close_date': trade.close_date or datetime.utcnow(),
|
||||||
'stake_amount': trade.stake_amount,
|
'stake_amount': trade.stake_amount,
|
||||||
'stake_currency': self.config['stake_currency'],
|
'stake_currency': self.config['stake_currency'],
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
'fiat_currency': self.config.get('fiat_display_currency'),
|
'fiat_currency': self.config.get('fiat_display_currency'),
|
||||||
'sub_trade': sub_trade,
|
'sub_trade': sub_trade,
|
||||||
'cumulative_profit': trade.realized_profit,
|
'cumulative_profit': trade.realized_profit,
|
||||||
@ -1719,7 +1724,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
profit_ratio = trade.calc_profit_ratio(profit_rate)
|
profit_ratio = trade.calc_profit_ratio(profit_rate)
|
||||||
gain = "profit" if profit_ratio > 0 else "loss"
|
gain = "profit" if profit_ratio > 0 else "loss"
|
||||||
|
|
||||||
msg = {
|
msg: RPCSellCancelMsg = {
|
||||||
'type': RPCMessageType.EXIT_CANCEL,
|
'type': RPCMessageType.EXIT_CANCEL,
|
||||||
'trade_id': trade.id,
|
'trade_id': trade.id,
|
||||||
'exchange': trade.exchange.capitalize(),
|
'exchange': trade.exchange.capitalize(),
|
||||||
@ -1741,6 +1746,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
'open_date': trade.open_date,
|
'open_date': trade.open_date,
|
||||||
'close_date': trade.close_date or datetime.now(timezone.utc),
|
'close_date': trade.close_date or datetime.now(timezone.utc),
|
||||||
'stake_currency': self.config['stake_currency'],
|
'stake_currency': self.config['stake_currency'],
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(trade.pair),
|
||||||
'fiat_currency': self.config.get('fiat_display_currency', None),
|
'fiat_currency': self.config.get('fiat_display_currency', None),
|
||||||
'reason': reason,
|
'reason': reason,
|
||||||
'sub_trade': sub_trade,
|
'sub_trade': sub_trade,
|
||||||
@ -1848,14 +1854,20 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
self.strategy.lock_pair(pair, datetime.now(timezone.utc), reason='Auto lock')
|
self.strategy.lock_pair(pair, datetime.now(timezone.utc), reason='Auto lock')
|
||||||
prot_trig = self.protections.stop_per_pair(pair, side=side)
|
prot_trig = self.protections.stop_per_pair(pair, side=side)
|
||||||
if prot_trig:
|
if prot_trig:
|
||||||
msg = {'type': RPCMessageType.PROTECTION_TRIGGER, }
|
msg: RPCProtectionMsg = {
|
||||||
msg.update(prot_trig.to_json())
|
'type': RPCMessageType.PROTECTION_TRIGGER,
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(prot_trig.pair),
|
||||||
|
**prot_trig.to_json() # type: ignore
|
||||||
|
}
|
||||||
self.rpc.send_msg(msg)
|
self.rpc.send_msg(msg)
|
||||||
|
|
||||||
prot_trig_glb = self.protections.global_stop(side=side)
|
prot_trig_glb = self.protections.global_stop(side=side)
|
||||||
if prot_trig_glb:
|
if prot_trig_glb:
|
||||||
msg = {'type': RPCMessageType.PROTECTION_TRIGGER_GLOBAL, }
|
msg = {
|
||||||
msg.update(prot_trig_glb.to_json())
|
'type': RPCMessageType.PROTECTION_TRIGGER_GLOBAL,
|
||||||
|
'base_currency': self.exchange.get_pair_base_currency(prot_trig_glb.pair),
|
||||||
|
**prot_trig_glb.to_json() # type: ignore
|
||||||
|
}
|
||||||
self.rpc.send_msg(msg)
|
self.rpc.send_msg(msg)
|
||||||
|
|
||||||
def apply_fee_conditional(self, trade: Trade, trade_base_currency: str,
|
def apply_fee_conditional(self, trade: Trade, trade_base_currency: str,
|
||||||
|
@ -13,6 +13,7 @@ from freqtrade.exceptions import OperationalException
|
|||||||
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
|
from freqtrade.rpc.api_server.uvicorn_threaded import UvicornServer
|
||||||
from freqtrade.rpc.api_server.ws.message_stream import MessageStream
|
from freqtrade.rpc.api_server.ws.message_stream import MessageStream
|
||||||
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
from freqtrade.rpc.rpc import RPC, RPCException, RPCHandler
|
||||||
|
from freqtrade.rpc.rpc_types import RPCSendMsg
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -108,7 +109,7 @@ class ApiServer(RPCHandler):
|
|||||||
cls._has_rpc = False
|
cls._has_rpc = False
|
||||||
cls._rpc = None
|
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
|
Publish the message to the message stream
|
||||||
"""
|
"""
|
||||||
|
@ -30,6 +30,7 @@ from freqtrade.persistence import Order, PairLocks, Trade
|
|||||||
from freqtrade.persistence.models import PairLock
|
from freqtrade.persistence.models import PairLock
|
||||||
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
|
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
|
||||||
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
|
from freqtrade.rpc.fiat_convert import CryptoToFiatConverter
|
||||||
|
from freqtrade.rpc.rpc_types import RPCSendMsg
|
||||||
from freqtrade.wallets import PositionWallet, Wallet
|
from freqtrade.wallets import PositionWallet, Wallet
|
||||||
|
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ class RPCHandler:
|
|||||||
""" Cleanup pending module resources """
|
""" Cleanup pending module resources """
|
||||||
|
|
||||||
@abstractmethod
|
@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 """
|
""" Sends a message to all registered rpc modules """
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,11 +3,12 @@ This module contains class to manage RPC communications (Telegram, API, ...)
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from typing import Any, Dict, List
|
from typing import List
|
||||||
|
|
||||||
from freqtrade.constants import Config
|
from freqtrade.constants import Config
|
||||||
from freqtrade.enums import NO_ECHO_MESSAGES, RPCMessageType
|
from freqtrade.enums import NO_ECHO_MESSAGES, RPCMessageType
|
||||||
from freqtrade.rpc import RPC, RPCHandler
|
from freqtrade.rpc import RPC, RPCHandler
|
||||||
|
from freqtrade.rpc.rpc_types import RPCSendMsg
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -58,7 +59,7 @@ class RPCManager:
|
|||||||
mod.cleanup()
|
mod.cleanup()
|
||||||
del mod
|
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.
|
Send given message to all registered rpc modules.
|
||||||
A message consists of one or more key value pairs of strings.
|
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:
|
if msg.get('type') not in NO_ECHO_MESSAGES:
|
||||||
logger.info('Sending rpc message: %s', msg)
|
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:
|
for mod in self.registered_modules:
|
||||||
logger.debug('Forwarding message to rpc.%s', mod.name)
|
logger.debug('Forwarding message to rpc.%s', mod.name)
|
||||||
try:
|
try:
|
||||||
|
128
freqtrade/rpc/rpc_types.py
Normal file
128
freqtrade/rpc/rpc_types.py
Normal 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
|
||||||
|
]
|
@ -30,6 +30,7 @@ from freqtrade.exceptions import OperationalException
|
|||||||
from freqtrade.misc import chunks, plural, round_coin_value
|
from freqtrade.misc import chunks, plural, round_coin_value
|
||||||
from freqtrade.persistence import Trade
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.rpc import RPC, RPCException, RPCHandler
|
from freqtrade.rpc import RPC, RPCException, RPCHandler
|
||||||
|
from freqtrade.rpc.rpc_types import RPCSendMsg
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -429,14 +430,14 @@ class Telegram(RPCHandler):
|
|||||||
return None
|
return None
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def send_msg(self, msg: Dict[str, Any]) -> None:
|
def send_msg(self, msg: RPCSendMsg) -> None:
|
||||||
""" Send a message to telegram channel """
|
""" Send a message to telegram channel """
|
||||||
|
|
||||||
default_noti = 'on'
|
default_noti = 'on'
|
||||||
|
|
||||||
msg_type = msg['type']
|
msg_type = msg['type']
|
||||||
noti = ''
|
noti = ''
|
||||||
if msg_type == RPCMessageType.EXIT:
|
if msg['type'] == RPCMessageType.EXIT:
|
||||||
sell_noti = self._config['telegram'] \
|
sell_noti = self._config['telegram'] \
|
||||||
.get('notification_settings', {}).get(str(msg_type), {})
|
.get('notification_settings', {}).get(str(msg_type), {})
|
||||||
# For backward compatibility sell still can be string
|
# For backward compatibility sell still can be string
|
||||||
@ -453,7 +454,7 @@ class Telegram(RPCHandler):
|
|||||||
# Notification disabled
|
# Notification disabled
|
||||||
return
|
return
|
||||||
|
|
||||||
message = self.compose_message(deepcopy(msg), msg_type)
|
message = self.compose_message(deepcopy(msg), msg_type) # type: ignore
|
||||||
if message:
|
if message:
|
||||||
self._send_msg(message, disable_notification=(noti == 'silent'))
|
self._send_msg(message, disable_notification=(noti == 'silent'))
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from requests import RequestException, post
|
|||||||
from freqtrade.constants import Config
|
from freqtrade.constants import Config
|
||||||
from freqtrade.enums import RPCMessageType
|
from freqtrade.enums import RPCMessageType
|
||||||
from freqtrade.rpc import RPC, RPCHandler
|
from freqtrade.rpc import RPC, RPCHandler
|
||||||
|
from freqtrade.rpc.rpc_types import RPCSendMsg
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -41,7 +42,7 @@ class Webhook(RPCHandler):
|
|||||||
"""
|
"""
|
||||||
pass
|
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']
|
whconfig = self._config['webhook']
|
||||||
# Deprecated 2022.10 - only keep generic method.
|
# Deprecated 2022.10 - only keep generic method.
|
||||||
if msg['type'] in [RPCMessageType.ENTRY]:
|
if msg['type'] in [RPCMessageType.ENTRY]:
|
||||||
@ -75,7 +76,7 @@ class Webhook(RPCHandler):
|
|||||||
return None
|
return None
|
||||||
return valuedict
|
return valuedict
|
||||||
|
|
||||||
def send_msg(self, msg: Dict[str, Any]) -> None:
|
def send_msg(self, msg: RPCSendMsg) -> None:
|
||||||
""" Send a message to telegram channel """
|
""" Send a message to telegram channel """
|
||||||
try:
|
try:
|
||||||
|
|
||||||
|
@ -3328,6 +3328,7 @@ def test_execute_trade_exit_up(default_conf_usdt, ticker_usdt, fee, ticker_usdt_
|
|||||||
'profit_ratio': 0.00493809 if is_short else 0.09451372,
|
'profit_ratio': 0.00493809 if is_short else 0.09451372,
|
||||||
'stake_currency': 'USDT',
|
'stake_currency': 'USDT',
|
||||||
'fiat_currency': 'USD',
|
'fiat_currency': 'USD',
|
||||||
|
'base_currency': 'ETH',
|
||||||
'sell_reason': ExitType.ROI.value,
|
'sell_reason': ExitType.ROI.value,
|
||||||
'exit_reason': ExitType.ROI.value,
|
'exit_reason': ExitType.ROI.value,
|
||||||
'open_date': ANY,
|
'open_date': ANY,
|
||||||
@ -3391,6 +3392,7 @@ def test_execute_trade_exit_down(default_conf_usdt, ticker_usdt, fee, ticker_usd
|
|||||||
'profit_amount': -5.65990099 if is_short else -0.00075,
|
'profit_amount': -5.65990099 if is_short else -0.00075,
|
||||||
'profit_ratio': -0.0945681 if is_short else -1.247e-05,
|
'profit_ratio': -0.0945681 if is_short else -1.247e-05,
|
||||||
'stake_currency': 'USDT',
|
'stake_currency': 'USDT',
|
||||||
|
'base_currency': 'ETH',
|
||||||
'fiat_currency': 'USD',
|
'fiat_currency': 'USD',
|
||||||
'sell_reason': ExitType.STOP_LOSS.value,
|
'sell_reason': ExitType.STOP_LOSS.value,
|
||||||
'exit_reason': ExitType.STOP_LOSS.value,
|
'exit_reason': ExitType.STOP_LOSS.value,
|
||||||
@ -3476,6 +3478,7 @@ def test_execute_trade_exit_custom_exit_price(
|
|||||||
'profit_amount': pytest.approx(profit_amount),
|
'profit_amount': pytest.approx(profit_amount),
|
||||||
'profit_ratio': profit_ratio,
|
'profit_ratio': profit_ratio,
|
||||||
'stake_currency': 'USDT',
|
'stake_currency': 'USDT',
|
||||||
|
'base_currency': 'ETH',
|
||||||
'fiat_currency': 'USD',
|
'fiat_currency': 'USD',
|
||||||
'sell_reason': 'foo',
|
'sell_reason': 'foo',
|
||||||
'exit_reason': 'foo',
|
'exit_reason': 'foo',
|
||||||
@ -3549,6 +3552,7 @@ def test_execute_trade_exit_down_stoploss_on_exchange_dry_run(
|
|||||||
'profit_ratio': -0.00501253 if is_short else -0.01493766,
|
'profit_ratio': -0.00501253 if is_short else -0.01493766,
|
||||||
'stake_currency': 'USDT',
|
'stake_currency': 'USDT',
|
||||||
'fiat_currency': 'USD',
|
'fiat_currency': 'USD',
|
||||||
|
'base_currency': 'ETH',
|
||||||
'sell_reason': ExitType.STOP_LOSS.value,
|
'sell_reason': ExitType.STOP_LOSS.value,
|
||||||
'exit_reason': ExitType.STOP_LOSS.value,
|
'exit_reason': ExitType.STOP_LOSS.value,
|
||||||
'open_date': ANY,
|
'open_date': ANY,
|
||||||
@ -3813,6 +3817,7 @@ def test_execute_trade_exit_market_order(
|
|||||||
'profit_amount': pytest.approx(profit_amount),
|
'profit_amount': pytest.approx(profit_amount),
|
||||||
'profit_ratio': profit_ratio,
|
'profit_ratio': profit_ratio,
|
||||||
'stake_currency': 'USDT',
|
'stake_currency': 'USDT',
|
||||||
|
'base_currency': 'ETH',
|
||||||
'fiat_currency': 'USD',
|
'fiat_currency': 'USD',
|
||||||
'sell_reason': ExitType.ROI.value,
|
'sell_reason': ExitType.ROI.value,
|
||||||
'exit_reason': ExitType.ROI.value,
|
'exit_reason': ExitType.ROI.value,
|
||||||
|
Loading…
Reference in New Issue
Block a user