Add more info on status message
This commit is contained in:
parent
3925e8a7e3
commit
05046b9eef
@ -282,6 +282,20 @@ class LocalTrade():
|
|||||||
return self.close_date.replace(tzinfo=timezone.utc)
|
return self.close_date.replace(tzinfo=timezone.utc)
|
||||||
|
|
||||||
def to_json(self) -> Dict[str, Any]:
|
def to_json(self) -> Dict[str, Any]:
|
||||||
|
fill_buy = self.select_filled_orders('buy')
|
||||||
|
buys_json = dict()
|
||||||
|
if len(fill_buy) > 0:
|
||||||
|
for x in range(len(fill_buy)):
|
||||||
|
buy = dict(
|
||||||
|
cost=fill_buy[x].cost if fill_buy[x].cost else 0.0,
|
||||||
|
amount=fill_buy[x].amount,
|
||||||
|
price=fill_buy[x].price,
|
||||||
|
average=round(fill_buy[x].average, 8) if fill_buy[x].average else 0.0,
|
||||||
|
order_filled_date=fill_buy[x].order_filled_date.strftime(DATETIME_PRINT_FORMAT)
|
||||||
|
if fill_buy[x].order_filled_date else None
|
||||||
|
)
|
||||||
|
buys_json[str(x)] = buy
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'trade_id': self.id,
|
'trade_id': self.id,
|
||||||
'pair': self.pair,
|
'pair': self.pair,
|
||||||
@ -345,6 +359,7 @@ class LocalTrade():
|
|||||||
'max_rate': self.max_rate,
|
'max_rate': self.max_rate,
|
||||||
|
|
||||||
'open_order_id': self.open_order_id,
|
'open_order_id': self.open_order_id,
|
||||||
|
'filled_buys': buys_json,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -208,6 +208,8 @@ class RPC:
|
|||||||
order['type'], order['side'], order['remaining']
|
order['type'], order['side'], order['remaining']
|
||||||
) if order else None,
|
) if order else None,
|
||||||
))
|
))
|
||||||
|
cp_cfg = self._config
|
||||||
|
trade_dict['position_adjustment_enable'] = cp_cfg['position_adjustment_enable']
|
||||||
results.append(trade_dict)
|
results.append(trade_dict)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@ -242,7 +244,7 @@ class RPC:
|
|||||||
trade.id,
|
trade.id,
|
||||||
trade.pair + ('*' if (trade.open_order_id is not None
|
trade.pair + ('*' if (trade.open_order_id is not None
|
||||||
and trade.close_rate_requested is None) else '')
|
and trade.close_rate_requested is None) else '')
|
||||||
+ ('**' if (trade.close_rate_requested is not None) else ''),
|
+ ('**' if (trade.close_rate_requested is not None) else ''),
|
||||||
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)),
|
shorten_date(arrow.get(trade.open_date).humanize(only_distance=True)),
|
||||||
profit_str
|
profit_str
|
||||||
]
|
]
|
||||||
|
@ -369,6 +369,47 @@ class Telegram(RPCHandler):
|
|||||||
else:
|
else:
|
||||||
return "\N{CROSS MARK}"
|
return "\N{CROSS MARK}"
|
||||||
|
|
||||||
|
def _prepare_buy_details(self, filled_trades, base_currency):
|
||||||
|
"""
|
||||||
|
Prepare details of trade with buy adjustment enabled
|
||||||
|
"""
|
||||||
|
lines = []
|
||||||
|
for x in range(len(filled_trades)):
|
||||||
|
cur_buy_date = arrow.get(filled_trades[str(x)]["order_filled_date"])
|
||||||
|
cur_buy_amount = filled_trades[str(x)]["amount"]
|
||||||
|
cur_buy_average = filled_trades[str(x)]["average"]
|
||||||
|
lines.append(" ")
|
||||||
|
if x == 0:
|
||||||
|
lines.append("*Buy #{}:*".format(x+1))
|
||||||
|
lines.append("*Buy Amount:* {} ({:.8f} {})"
|
||||||
|
.format(cur_buy_amount, filled_trades[str(x)]["cost"], base_currency))
|
||||||
|
lines.append("*Average Buy Price:* {}".format(cur_buy_average))
|
||||||
|
else:
|
||||||
|
sumA = 0
|
||||||
|
sumB = 0
|
||||||
|
for y in range(x):
|
||||||
|
sumA += (filled_trades[str(y)]["amount"] * filled_trades[str(y)]["average"])
|
||||||
|
sumB += filled_trades[str(y)]["amount"]
|
||||||
|
prev_avg_price = sumA/sumB
|
||||||
|
price_to_1st_buy = (cur_buy_average - filled_trades["0"]["average"]) \
|
||||||
|
/ filled_trades["0"]["average"]
|
||||||
|
minus_on_buy = (cur_buy_average - prev_avg_price)/prev_avg_price
|
||||||
|
dur_buys = cur_buy_date - arrow.get(filled_trades[str(x-1)]["order_filled_date"])
|
||||||
|
days = dur_buys.days
|
||||||
|
hours, remainder = divmod(dur_buys.seconds, 3600)
|
||||||
|
minutes, seconds = divmod(remainder, 60)
|
||||||
|
lines.append("*Buy #{}:* at {:.2%} avg profit".format(x+1, minus_on_buy))
|
||||||
|
lines.append("({})".format(cur_buy_date
|
||||||
|
.humanize(granularity=["day", "hour", "minute"])))
|
||||||
|
lines.append("*Buy Amount:* {} ({:.8f} {})"
|
||||||
|
.format(cur_buy_amount, filled_trades[str(x)]["cost"], base_currency))
|
||||||
|
lines.append("*Average Buy Price:* {} ({:.2%} from 1st buy rate)"
|
||||||
|
.format(cur_buy_average, price_to_1st_buy))
|
||||||
|
lines.append("*Filled at:* {}".format(filled_trades[str(x)]["order_filled_date"]))
|
||||||
|
lines.append("({}d {}h {}m {}s from previous buy)"
|
||||||
|
.format(days, hours, minutes, seconds))
|
||||||
|
return lines
|
||||||
|
|
||||||
@authorized_only
|
@authorized_only
|
||||||
def _status(self, update: Update, context: CallbackContext) -> None:
|
def _status(self, update: Update, context: CallbackContext) -> None:
|
||||||
"""
|
"""
|
||||||
@ -396,17 +437,31 @@ class Telegram(RPCHandler):
|
|||||||
messages = []
|
messages = []
|
||||||
for r in results:
|
for r in results:
|
||||||
r['open_date_hum'] = arrow.get(r['open_date']).humanize()
|
r['open_date_hum'] = arrow.get(r['open_date']).humanize()
|
||||||
|
r['filled_buys'] = r.get('filled_buys', [])
|
||||||
|
r['num_buys'] = len(r['filled_buys'])
|
||||||
|
r['sell_reason'] = r.get('sell_reason', "")
|
||||||
|
r['position_adjustment_enable'] = r.get('position_adjustment_enable', False)
|
||||||
lines = [
|
lines = [
|
||||||
"*Trade ID:* `{trade_id}` `(since {open_date_hum})`",
|
"*Trade ID:* `{trade_id}` `(since {open_date_hum})`",
|
||||||
"*Current Pair:* {pair}",
|
"*Current Pair:* {pair}",
|
||||||
"*Amount:* `{amount} ({stake_amount} {base_currency})`",
|
"*Amount:* `{amount} ({stake_amount} {base_currency})`",
|
||||||
"*Buy Tag:* `{buy_tag}`" if r['buy_tag'] else "",
|
"*Buy Tag:* `{buy_tag}`" if r['buy_tag'] else "",
|
||||||
|
"*Sell Reason:* `{sell_reason}`" if r['sell_reason'] else "",
|
||||||
|
]
|
||||||
|
|
||||||
|
if r['position_adjustment_enable']:
|
||||||
|
lines.append("*Number of Buy(s):* `{num_buys}`")
|
||||||
|
|
||||||
|
lines.extend([
|
||||||
"*Open Rate:* `{open_rate:.8f}`",
|
"*Open Rate:* `{open_rate:.8f}`",
|
||||||
"*Close Rate:* `{close_rate}`" if r['close_rate'] else "",
|
"*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}`",
|
"*Current Rate:* `{current_rate:.8f}`",
|
||||||
("*Current Profit:* " if r['is_open'] else "*Close Profit: *")
|
("*Current Profit:* " if r['is_open'] else "*Close Profit: *")
|
||||||
+ "`{profit_ratio:.2%}`",
|
+ "`{profit_ratio:.2%}`",
|
||||||
]
|
])
|
||||||
|
|
||||||
if (r['stop_loss_abs'] != r['initial_stop_loss_abs']
|
if (r['stop_loss_abs'] != r['initial_stop_loss_abs']
|
||||||
and r['initial_stop_loss_ratio'] is not None):
|
and r['initial_stop_loss_ratio'] is not None):
|
||||||
# Adding initial stoploss only if it is different from stoploss
|
# Adding initial stoploss only if it is different from stoploss
|
||||||
@ -424,6 +479,10 @@ class Telegram(RPCHandler):
|
|||||||
else:
|
else:
|
||||||
lines.append("*Open Order:* `{open_order}`")
|
lines.append("*Open Order:* `{open_order}`")
|
||||||
|
|
||||||
|
if len(r['filled_buys']) > 1:
|
||||||
|
lines_detail = self._prepare_buy_details(r['filled_buys'], r['base_currency'])
|
||||||
|
lines.extend(lines_detail)
|
||||||
|
|
||||||
# Filter empty lines using list-comprehension
|
# Filter empty lines using list-comprehension
|
||||||
messages.append("\n".join([line for line in lines if line]).format(**r))
|
messages.append("\n".join([line for line in lines if line]).format(**r))
|
||||||
|
|
||||||
|
@ -108,6 +108,9 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
|||||||
'stoploss_entry_dist_ratio': -0.10448878,
|
'stoploss_entry_dist_ratio': -0.10448878,
|
||||||
'open_order': None,
|
'open_order': None,
|
||||||
'exchange': 'binance',
|
'exchange': 'binance',
|
||||||
|
'position_adjustment_enable': False,
|
||||||
|
'filled_buys': {'0': {'amount': 91.07468123, 'average': 1.098e-05,
|
||||||
|
'cost': 0.0009999999999054, 'order_filled_date': ANY, 'price': 1.098e-05}},
|
||||||
}
|
}
|
||||||
|
|
||||||
mocker.patch('freqtrade.exchange.Exchange.get_rate',
|
mocker.patch('freqtrade.exchange.Exchange.get_rate',
|
||||||
@ -175,6 +178,9 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
|||||||
'stoploss_entry_dist_ratio': -0.10448878,
|
'stoploss_entry_dist_ratio': -0.10448878,
|
||||||
'open_order': None,
|
'open_order': None,
|
||||||
'exchange': 'binance',
|
'exchange': 'binance',
|
||||||
|
'position_adjustment_enable': False,
|
||||||
|
'filled_buys': {'0': {'amount': 91.07468123, 'average': 1.098e-05,
|
||||||
|
'cost': 0.0009999999999054, 'order_filled_date': ANY, 'price': 1.098e-05}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -903,6 +903,7 @@ def test_to_json(default_conf, fee):
|
|||||||
'buy_tag': None,
|
'buy_tag': None,
|
||||||
'timeframe': None,
|
'timeframe': None,
|
||||||
'exchange': 'binance',
|
'exchange': 'binance',
|
||||||
|
'filled_buys': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Simulate dry_run entries
|
# Simulate dry_run entries
|
||||||
@ -970,6 +971,7 @@ def test_to_json(default_conf, fee):
|
|||||||
'buy_tag': 'buys_signal_001',
|
'buy_tag': 'buys_signal_001',
|
||||||
'timeframe': None,
|
'timeframe': None,
|
||||||
'exchange': 'binance',
|
'exchange': 'binance',
|
||||||
|
'filled_buys': {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user