This commit is contained in:
Stefano Ariestasia 2022-01-26 07:06:52 +00:00
parent 480ed90a02
commit 1f26709aca
5 changed files with 59 additions and 33 deletions

View File

@ -167,12 +167,23 @@ class Order(_DECL_BASE):
def to_json(self) -> Dict[str, Any]: def to_json(self) -> Dict[str, Any]:
return { return {
'cost': self.cost if self.cost else 0,
'amount': self.amount, 'amount': self.amount,
'price': self.price,
'average': round(self.average, 8) if self.average else 0, 'average': round(self.average, 8) if self.average else 0,
'cost': self.cost if self.cost else 0,
'filled': self.filled,
'ft_order_side': self.ft_order_side,
'order_date': self.order_date.strftime(DATETIME_PRINT_FORMAT)
if self.order_date else None,
'order_timestamp': int(self.order_date.replace(
tzinfo=timezone.utc).timestamp() * 1000) if self.order_date else None,
'order_filled_date': self.order_filled_date.strftime(DATETIME_PRINT_FORMAT) 'order_filled_date': self.order_filled_date.strftime(DATETIME_PRINT_FORMAT)
if self.order_filled_date else None if self.order_filled_date else None,
'order_filled_timestamp': int(self.order_filled_date.replace(
tzinfo=timezone.utc).timestamp() * 1000) if self.order_filled_date else None,
'order_type': self.order_type,
'price': self.price,
'remaining': self.remaining,
'status': self.status,
} }
@staticmethod @staticmethod
@ -292,11 +303,15 @@ 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') filled_orders = self.select_filled_orders()
buys_json = dict() filled_buys = []
if len(fill_buy) > 0: filled_sells = []
for x in range(len(fill_buy)): if len(filled_orders) > 0:
buys_json[str(x)] = fill_buy[x].to_json() for x in range(len(filled_orders)):
if filled_orders[x].ft_order_side == 'buy':
filled_buys.append(filled_orders[x].to_json())
elif filled_orders[x].ft_order_side == 'sell':
filled_sells.append(filled_orders[x].to_json())
return { return {
'trade_id': self.id, 'trade_id': self.id,
@ -361,7 +376,8 @@ 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, 'filled_buys': filled_buys,
'filled_sells': filled_sells,
} }
@staticmethod @staticmethod
@ -631,14 +647,14 @@ class LocalTrade():
else: else:
return None return None
def select_filled_orders(self, order_side: str) -> List['Order']: def select_filled_orders(self, order_side: Optional[str] = None) -> List['Order']:
""" """
Finds filled orders for this orderside. Finds filled orders for this orderside.
:param order_side: Side of the order (either 'buy' or 'sell') :param order_side: Side of the order (either 'buy', 'sell', or None)
:return: array of Order objects :return: array of Order objects
""" """
return [o for o in self.orders if o.ft_order_side == order_side and return [o for o in self.orders if ((o.ft_order_side == order_side) or (order_side is None))
o.ft_is_open is False and and o.ft_is_open is False and
(o.filled or 0) > 0 and (o.filled or 0) > 0 and
o.status in NON_OPEN_EXCHANGE_STATES] o.status in NON_OPEN_EXCHANGE_STATES]

View File

@ -375,37 +375,37 @@ class Telegram(RPCHandler):
""" """
lines = [] lines = []
for x in range(len(filled_trades)): for x in range(len(filled_trades)):
cur_buy_date = arrow.get(filled_trades[str(x)]["order_filled_date"]) current_buy_datetime = arrow.get(filled_trades[x]["order_filled_date"])
cur_buy_amount = filled_trades[str(x)]["amount"] cur_buy_amount = filled_trades[x]["amount"]
cur_buy_average = filled_trades[str(x)]["average"] cur_buy_average = filled_trades[x]["average"]
lines.append(" ") lines.append(" ")
if x == 0: if x == 0:
lines.append("*Buy #{}:*".format(x+1)) lines.append("*Buy #{}:*".format(x+1))
lines.append("*Buy Amount:* {} ({:.8f} {})" lines.append("*Buy Amount:* {} ({:.8f} {})"
.format(cur_buy_amount, filled_trades[str(x)]["cost"], base_currency)) .format(cur_buy_amount, filled_trades[x]["cost"], base_currency))
lines.append("*Average Buy Price:* {}".format(cur_buy_average)) lines.append("*Average Buy Price:* {}".format(cur_buy_average))
else: else:
sumA = 0 sumA = 0
sumB = 0 sumB = 0
for y in range(x): for y in range(x):
sumA += (filled_trades[str(y)]["amount"] * filled_trades[str(y)]["average"]) sumA += (filled_trades[y]["amount"] * filled_trades[y]["average"])
sumB += filled_trades[str(y)]["amount"] sumB += filled_trades[y]["amount"]
prev_avg_price = sumA/sumB prev_avg_price = sumA/sumB
price_to_1st_buy = (cur_buy_average - filled_trades["0"]["average"]) \ price_to_1st_buy = (cur_buy_average - filled_trades[0]["average"]) \
/ filled_trades["0"]["average"] / filled_trades[0]["average"]
minus_on_buy = (cur_buy_average - prev_avg_price)/prev_avg_price 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"]) dur_buys = current_buy_datetime - arrow.get(filled_trades[x-1]["order_filled_date"])
days = dur_buys.days days = dur_buys.days
hours, remainder = divmod(dur_buys.seconds, 3600) hours, remainder = divmod(dur_buys.seconds, 3600)
minutes, seconds = divmod(remainder, 60) minutes, seconds = divmod(remainder, 60)
lines.append("*Buy #{}:* at {:.2%} avg profit".format(x+1, minus_on_buy)) lines.append("*Buy #{}:* at {:.2%} avg profit".format(x+1, minus_on_buy))
lines.append("({})".format(cur_buy_date lines.append("({})".format(current_buy_datetime
.humanize(granularity=["day", "hour", "minute"]))) .humanize(granularity=["day", "hour", "minute"])))
lines.append("*Buy Amount:* {} ({:.8f} {})" lines.append("*Buy Amount:* {} ({:.8f} {})"
.format(cur_buy_amount, filled_trades[str(x)]["cost"], base_currency)) .format(cur_buy_amount, filled_trades[x]["cost"], base_currency))
lines.append("*Average Buy Price:* {} ({:.2%} from 1st buy rate)" lines.append("*Average Buy Price:* {} ({:.2%} from 1st buy rate)"
.format(cur_buy_average, price_to_1st_buy)) .format(cur_buy_average, price_to_1st_buy))
lines.append("*Filled at:* {}".format(filled_trades[str(x)]["order_filled_date"])) lines.append("*Order filled at:* {}".format(filled_trades[x]["order_filled_date"]))
lines.append("({}d {}h {}m {}s from previous buy)" lines.append("({}d {}h {}m {}s from previous buy)"
.format(days, hours, minutes, seconds)) .format(days, hours, minutes, seconds))
return lines return lines
@ -437,7 +437,6 @@ 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['num_buys'] = len(r['filled_buys'])
r['sell_reason'] = r.get('sell_reason', "") r['sell_reason'] = r.get('sell_reason', "")
r['position_adjustment_enable'] = r.get('position_adjustment_enable', False) r['position_adjustment_enable'] = r.get('position_adjustment_enable', False)

View File

@ -109,8 +109,12 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'open_order': None, 'open_order': None,
'exchange': 'binance', 'exchange': 'binance',
'position_adjustment_enable': False, 'position_adjustment_enable': False,
'filled_buys': {'0': {'amount': 91.07468123, 'average': 1.098e-05, 'filled_buys': [{'amount': 91.07468123, 'average': 1.098e-05,
'cost': 0.0009999999999054, 'order_filled_date': ANY, 'price': 1.098e-05}}, 'cost': 0.0009999999999054, 'filled': 91.07468123, 'ft_order_side': 'buy',
'order_date': ANY, 'order_timestamp': ANY, 'order_filled_date': ANY,
'order_filled_timestamp': ANY, 'order_type': 'limit', 'price': 1.098e-05,
'remaining': ANY, 'status': ANY}],
'filled_sells': []
} }
mocker.patch('freqtrade.exchange.Exchange.get_rate', mocker.patch('freqtrade.exchange.Exchange.get_rate',
@ -179,8 +183,12 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'open_order': None, 'open_order': None,
'exchange': 'binance', 'exchange': 'binance',
'position_adjustment_enable': False, 'position_adjustment_enable': False,
'filled_buys': {'0': {'amount': 91.07468123, 'average': 1.098e-05, 'filled_buys': [{'amount': 91.07468123, 'average': 1.098e-05,
'cost': 0.0009999999999054, 'order_filled_date': ANY, 'price': 1.098e-05}}, 'cost': 0.0009999999999054, 'filled': 91.07468123, 'ft_order_side': 'buy',
'order_date': ANY, 'order_timestamp': ANY, 'order_filled_date': ANY,
'order_filled_timestamp': ANY, 'order_type': 'limit', 'price': 1.098e-05,
'remaining': ANY, 'status': ANY}],
'filled_sells': []
} }

View File

@ -201,7 +201,8 @@ def test_telegram_status(default_conf, update, mocker) -> None:
'stoploss_current_dist_ratio': -0.0002, 'stoploss_current_dist_ratio': -0.0002,
'stop_loss_ratio': -0.0001, 'stop_loss_ratio': -0.0001,
'open_order': '(limit buy rem=0.00000000)', 'open_order': '(limit buy rem=0.00000000)',
'is_open': True 'is_open': True,
'filled_buys': []
}]), }]),
) )

View File

@ -903,7 +903,8 @@ def test_to_json(default_conf, fee):
'buy_tag': None, 'buy_tag': None,
'timeframe': None, 'timeframe': None,
'exchange': 'binance', 'exchange': 'binance',
'filled_buys': {} 'filled_buys': [],
'filled_sells': []
} }
# Simulate dry_run entries # Simulate dry_run entries
@ -971,7 +972,8 @@ 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': {} 'filled_buys': [],
'filled_sells': []
} }