mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
A few more formatting updates
This commit is contained in:
parent
6a802f5624
commit
9291698561
|
@ -73,9 +73,9 @@ def ask_user_config() -> Dict[str, Any]:
|
|||
"message": f"Please insert your stake amount (Number or '{UNLIMITED_STAKE_AMOUNT}'):",
|
||||
"default": "unlimited",
|
||||
"validate": lambda val: val == UNLIMITED_STAKE_AMOUNT or validate_is_float(val),
|
||||
"filter": lambda val: '"' + UNLIMITED_STAKE_AMOUNT + '"'
|
||||
if val == UNLIMITED_STAKE_AMOUNT
|
||||
else val,
|
||||
"filter": lambda val: (
|
||||
'"' + UNLIMITED_STAKE_AMOUNT + '"' if val == UNLIMITED_STAKE_AMOUNT else val
|
||||
),
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
|
|
|
@ -340,9 +340,9 @@ AVAILABLE_CLI_OPTIONS = {
|
|||
"hyperopt_loss": Arg(
|
||||
"--hyperopt-loss",
|
||||
"--hyperoptloss",
|
||||
help='Specify the class name of the hyperopt loss function class (IHyperOptLoss). '
|
||||
'Different functions can generate completely different results, '
|
||||
'since the target for optimization is different. Built-in Hyperopt-loss-functions are: '
|
||||
help="Specify the class name of the hyperopt loss function class (IHyperOptLoss). "
|
||||
"Different functions can generate completely different results, "
|
||||
"since the target for optimization is different. Built-in Hyperopt-loss-functions are: "
|
||||
f'{", ".join(HYPEROPT_LOSS_BUILTIN)}',
|
||||
metavar="NAME",
|
||||
),
|
||||
|
|
|
@ -41,9 +41,11 @@ def _flat_vars_to_nested_dict(env_dict: Dict[str, Any], prefix: str) -> Dict[str
|
|||
key = env_var.replace(prefix, "")
|
||||
for k in reversed(key.split("__")):
|
||||
val = {
|
||||
k.lower(): _get_var_typed(val)
|
||||
if not isinstance(val, dict) and k not in no_convert
|
||||
else val
|
||||
k.lower(): (
|
||||
_get_var_typed(val)
|
||||
if not isinstance(val, dict) and k not in no_convert
|
||||
else val
|
||||
)
|
||||
}
|
||||
relevant_vars = deep_merge_dicts(val, relevant_vars)
|
||||
return relevant_vars
|
||||
|
|
|
@ -262,7 +262,7 @@ def _download_pair_history(
|
|||
|
||||
logger.info(
|
||||
f'({process}) - Download history data for "{pair}", {timeframe}, '
|
||||
f'{candle_type} and store in {datadir}. '
|
||||
f"{candle_type} and store in {datadir}. "
|
||||
f'From {format_ms_time(since_ms) if since_ms else "start"} to '
|
||||
f'{format_ms_time(until_ms) if until_ms else "now"}'
|
||||
)
|
||||
|
@ -280,9 +280,11 @@ def _download_pair_history(
|
|||
new_data = exchange.get_historic_ohlcv(
|
||||
pair=pair,
|
||||
timeframe=timeframe,
|
||||
since_ms=since_ms
|
||||
if since_ms
|
||||
else int((datetime.now() - timedelta(days=new_pairs_days)).timestamp()) * 1000,
|
||||
since_ms=(
|
||||
since_ms
|
||||
if since_ms
|
||||
else int((datetime.now() - timedelta(days=new_pairs_days)).timestamp()) * 1000
|
||||
),
|
||||
is_new_pair=data.empty,
|
||||
candle_type=candle_type,
|
||||
until_ms=until_ms if until_ms else None,
|
||||
|
|
|
@ -33,17 +33,17 @@ def check_exchange(config: Config, check_for_bad: bool = True) -> bool:
|
|||
exchange = config.get("exchange", {}).get("name", "").lower()
|
||||
if not exchange:
|
||||
raise OperationalException(
|
||||
f'This command requires a configured exchange. You should either use '
|
||||
f'`--exchange <exchange_name>` or specify a configuration file via `--config`.\n'
|
||||
f'The following exchanges are available for Freqtrade: '
|
||||
f"This command requires a configured exchange. You should either use "
|
||||
f"`--exchange <exchange_name>` or specify a configuration file via `--config`.\n"
|
||||
f"The following exchanges are available for Freqtrade: "
|
||||
f'{", ".join(available_exchanges())}'
|
||||
)
|
||||
|
||||
if not is_exchange_known_ccxt(exchange):
|
||||
raise OperationalException(
|
||||
f'Exchange "{exchange}" is not known to the ccxt library '
|
||||
f'and therefore not available for the bot.\n'
|
||||
f'The following exchanges are available for Freqtrade: '
|
||||
f"and therefore not available for the bot.\n"
|
||||
f"The following exchanges are available for Freqtrade: "
|
||||
f'{", ".join(available_exchanges())}'
|
||||
)
|
||||
|
||||
|
|
|
@ -1310,8 +1310,8 @@ class FreqtradeBot(LoggingMixin):
|
|||
if should_exit.exit_flag:
|
||||
exit_tag1 = exit_tag if should_exit.exit_type == ExitType.EXIT_SIGNAL else None
|
||||
logger.info(
|
||||
f'Exit for {trade.pair} detected. Reason: {should_exit.exit_type}'
|
||||
f'{f" Tag: {exit_tag1}" if exit_tag1 is not None else ""}'
|
||||
f"Exit for {trade.pair} detected. Reason: {should_exit.exit_type}"
|
||||
f"{f' Tag: {exit_tag1}' if exit_tag1 is not None else ''}"
|
||||
)
|
||||
exited = self.execute_trade_exit(trade, exit_rate, should_exit, exit_tag=exit_tag1)
|
||||
if exited:
|
||||
|
|
|
@ -230,9 +230,11 @@ class Hyperopt:
|
|||
result["trailing"] = self.custom_hyperopt.generate_trailing_params(params)
|
||||
if HyperoptTools.has_space(self.config, "trades"):
|
||||
result["max_open_trades"] = {
|
||||
"max_open_trades": self.backtesting.strategy.max_open_trades
|
||||
if self.backtesting.strategy.max_open_trades != float("inf")
|
||||
else -1
|
||||
"max_open_trades": (
|
||||
self.backtesting.strategy.max_open_trades
|
||||
if self.backtesting.strategy.max_open_trades != float("inf")
|
||||
else -1
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
@ -457,11 +457,13 @@ class HyperoptTools:
|
|||
lambda x: f"{x:,.2%}".rjust(7, " ") if not isna(x) else "--".rjust(7, " ")
|
||||
)
|
||||
trials["Avg duration"] = trials["Avg duration"].apply(
|
||||
lambda x: f"{x:,.1f} m".rjust(7, " ")
|
||||
if isinstance(x, float)
|
||||
else f"{x}"
|
||||
if not isna(x)
|
||||
else "--".rjust(7, " ")
|
||||
lambda x: (
|
||||
f"{x:,.1f} m".rjust(7, " ")
|
||||
if isinstance(x, float)
|
||||
else f"{x}"
|
||||
if not isna(x)
|
||||
else "--".rjust(7, " ")
|
||||
)
|
||||
)
|
||||
trials["Objective"] = trials["Objective"].apply(
|
||||
lambda x: f"{x:,.5f}".rjust(8, " ") if x != 100000 else "N/A".rjust(8, " ")
|
||||
|
@ -470,28 +472,32 @@ class HyperoptTools:
|
|||
stake_currency = config["stake_currency"]
|
||||
|
||||
trials[f"Max Drawdown{' (Acct)' if has_account_drawdown else ''}"] = trials.apply(
|
||||
lambda x: "{} {}".format(
|
||||
fmt_coin(x["max_drawdown_abs"], stake_currency, keep_trailing_zeros=True),
|
||||
(
|
||||
f"({x['max_drawdown_account']:,.2%})"
|
||||
if has_account_drawdown
|
||||
else f"({x['max_drawdown']:,.2%})"
|
||||
).rjust(10, " "),
|
||||
).rjust(25 + len(stake_currency))
|
||||
if x["max_drawdown"] != 0.0 or x["max_drawdown_account"] != 0.0
|
||||
else "--".rjust(25 + len(stake_currency)),
|
||||
lambda x: (
|
||||
"{} {}".format(
|
||||
fmt_coin(x["max_drawdown_abs"], stake_currency, keep_trailing_zeros=True),
|
||||
(
|
||||
f"({x['max_drawdown_account']:,.2%})"
|
||||
if has_account_drawdown
|
||||
else f"({x['max_drawdown']:,.2%})"
|
||||
).rjust(10, " "),
|
||||
).rjust(25 + len(stake_currency))
|
||||
if x["max_drawdown"] != 0.0 or x["max_drawdown_account"] != 0.0
|
||||
else "--".rjust(25 + len(stake_currency))
|
||||
),
|
||||
axis=1,
|
||||
)
|
||||
|
||||
trials = trials.drop(columns=["max_drawdown_abs", "max_drawdown", "max_drawdown_account"])
|
||||
|
||||
trials["Profit"] = trials.apply(
|
||||
lambda x: "{} {}".format(
|
||||
fmt_coin(x["Total profit"], stake_currency, keep_trailing_zeros=True),
|
||||
f"({x['Profit']:,.2%})".rjust(10, " "),
|
||||
).rjust(25 + len(stake_currency))
|
||||
if x["Total profit"] != 0.0
|
||||
else "--".rjust(25 + len(stake_currency)),
|
||||
lambda x: (
|
||||
"{} {}".format(
|
||||
fmt_coin(x["Total profit"], stake_currency, keep_trailing_zeros=True),
|
||||
f"({x['Profit']:,.2%})".rjust(10, " "),
|
||||
).rjust(25 + len(stake_currency))
|
||||
if x["Total profit"] != 0.0
|
||||
else "--".rjust(25 + len(stake_currency))
|
||||
),
|
||||
axis=1,
|
||||
)
|
||||
trials = trials.drop(columns=["Total profit"])
|
||||
|
|
|
@ -89,9 +89,11 @@ def text_table_tags(tag_type: str, tag_results: List[Dict[str, Any]], stake_curr
|
|||
floatfmt = _get_line_floatfmt(stake_currency)
|
||||
output = [
|
||||
[
|
||||
t["key"]
|
||||
if t.get("key") is not None and len(str(t["key"])) > 0
|
||||
else t.get(fallback, "OTHER"),
|
||||
(
|
||||
t["key"]
|
||||
if t.get("key") is not None and len(str(t["key"])) > 0
|
||||
else t.get(fallback, "OTHER")
|
||||
),
|
||||
t["trades"],
|
||||
t["profit_mean_pct"],
|
||||
t["profit_total_abs"],
|
||||
|
@ -218,9 +220,11 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
|||
)
|
||||
drawdown_metrics.extend(
|
||||
[
|
||||
("Absolute Drawdown (Account)", f"{strat_results['max_drawdown_account']:.2%}")
|
||||
if "max_drawdown_account" in strat_results
|
||||
else ("Drawdown", f"{strat_results['max_drawdown']:.2%}"),
|
||||
(
|
||||
("Absolute Drawdown (Account)", f"{strat_results['max_drawdown_account']:.2%}")
|
||||
if "max_drawdown_account" in strat_results
|
||||
else ("Drawdown", f"{strat_results['max_drawdown']:.2%}")
|
||||
),
|
||||
(
|
||||
"Absolute Drawdown",
|
||||
fmt_coin(strat_results["max_drawdown_abs"], strat_results["stake_currency"]),
|
||||
|
@ -279,9 +283,11 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
|||
("Calmar", f"{strat_results['calmar']:.2f}" if "calmar" in strat_results else "N/A"),
|
||||
(
|
||||
"Profit factor",
|
||||
f'{strat_results["profit_factor"]:.2f}'
|
||||
if "profit_factor" in strat_results
|
||||
else "N/A",
|
||||
(
|
||||
f'{strat_results["profit_factor"]:.2f}'
|
||||
if "profit_factor" in strat_results
|
||||
else "N/A"
|
||||
),
|
||||
),
|
||||
(
|
||||
"Expectancy (Ratio)",
|
||||
|
@ -335,11 +341,13 @@ def text_table_add_metrics(strat_results: Dict) -> str:
|
|||
(
|
||||
"Max Consecutive Wins / Loss",
|
||||
(
|
||||
f"{strat_results['max_consecutive_wins']} / "
|
||||
f"{strat_results['max_consecutive_losses']}"
|
||||
)
|
||||
if "max_consecutive_losses" in strat_results
|
||||
else "N/A",
|
||||
(
|
||||
f"{strat_results['max_consecutive_wins']} / "
|
||||
f"{strat_results['max_consecutive_losses']}"
|
||||
)
|
||||
if "max_consecutive_losses" in strat_results
|
||||
else "N/A"
|
||||
),
|
||||
),
|
||||
("Rejected Entry signals", strat_results.get("rejected_signals", "N/A")),
|
||||
(
|
||||
|
|
|
@ -80,17 +80,19 @@ def _generate_result_line(result: DataFrame, starting_balance: int, first_column
|
|||
"key": first_column,
|
||||
"trades": len(result),
|
||||
"profit_mean": result["profit_ratio"].mean() if len(result) > 0 else 0.0,
|
||||
"profit_mean_pct": round(result["profit_ratio"].mean() * 100.0, 2)
|
||||
if len(result) > 0
|
||||
else 0.0,
|
||||
"profit_mean_pct": (
|
||||
round(result["profit_ratio"].mean() * 100.0, 2) if len(result) > 0 else 0.0
|
||||
),
|
||||
"profit_sum": profit_sum,
|
||||
"profit_sum_pct": round(profit_sum * 100.0, 2),
|
||||
"profit_total_abs": result["profit_abs"].sum(),
|
||||
"profit_total": profit_total,
|
||||
"profit_total_pct": round(profit_total * 100.0, 2),
|
||||
"duration_avg": str(timedelta(minutes=round(result["trade_duration"].mean())))
|
||||
if not result.empty
|
||||
else "0:00",
|
||||
"duration_avg": (
|
||||
str(timedelta(minutes=round(result["trade_duration"].mean())))
|
||||
if not result.empty
|
||||
else "0:00"
|
||||
),
|
||||
# 'duration_max': str(timedelta(
|
||||
# minutes=round(result['trade_duration'].max()))
|
||||
# ) if not result.empty else '0:00',
|
||||
|
|
|
@ -164,7 +164,8 @@ def migrate_trades_and_orders_table(
|
|||
# Copy data back - following the correct schema
|
||||
with engine.begin() as connection:
|
||||
connection.execute(
|
||||
text(f"""insert into trades
|
||||
text(
|
||||
f"""insert into trades
|
||||
(id, exchange, pair, base_currency, stake_currency, is_open,
|
||||
fee_open, fee_open_cost, fee_open_currency,
|
||||
fee_close, fee_close_cost, fee_close_currency, open_rate,
|
||||
|
@ -209,7 +210,8 @@ def migrate_trades_and_orders_table(
|
|||
{precision_mode} precision_mode, {contract_size} contract_size,
|
||||
{max_stake_amount} max_stake_amount
|
||||
from {trade_back_name}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
migrate_orders_table(engine, order_back_name, cols_order)
|
||||
|
@ -238,7 +240,8 @@ def migrate_orders_table(engine, table_back_name: str, cols_order: List):
|
|||
# sqlite does not support literals for booleans
|
||||
with engine.begin() as connection:
|
||||
connection.execute(
|
||||
text(f"""
|
||||
text(
|
||||
f"""
|
||||
insert into orders (id, ft_trade_id, ft_order_side, ft_pair, ft_is_open, order_id,
|
||||
status, symbol, order_type, side, price, amount, filled, average, remaining, cost,
|
||||
stop_price, order_date, order_filled_date, order_update_date, ft_fee_base, funding_fee,
|
||||
|
@ -251,7 +254,8 @@ def migrate_orders_table(engine, table_back_name: str, cols_order: List):
|
|||
{ft_amount} ft_amount, {ft_price} ft_price, {ft_cancel_reason} ft_cancel_reason,
|
||||
{ft_order_tag} ft_order_tag
|
||||
from {table_back_name}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
@ -269,13 +273,15 @@ def migrate_pairlocks_table(decl_base, inspector, engine, pairlock_back_name: st
|
|||
# Copy data back - following the correct schema
|
||||
with engine.begin() as connection:
|
||||
connection.execute(
|
||||
text(f"""insert into pairlocks
|
||||
text(
|
||||
f"""insert into pairlocks
|
||||
(id, pair, side, reason, lock_time,
|
||||
lock_end_time, active)
|
||||
select id, pair, {side} side, reason, lock_time,
|
||||
lock_end_time, active
|
||||
from {pairlock_back_name}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -266,17 +266,19 @@ class Order(ModelBase):
|
|||
"cost": self.cost if self.cost else 0,
|
||||
"filled": self.filled,
|
||||
"is_open": self.ft_is_open,
|
||||
"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)
|
||||
if self.order_filled_date
|
||||
else None,
|
||||
"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)
|
||||
if self.order_filled_date
|
||||
else None
|
||||
),
|
||||
"order_type": self.order_type,
|
||||
"price": self.price,
|
||||
"remaining": self.remaining,
|
||||
|
|
|
@ -379,9 +379,9 @@ def pair_history_filtered(
|
|||
{
|
||||
"strategy": payload.strategy,
|
||||
"timerange": payload.timerange,
|
||||
"freqaimodel": payload.freqaimodel
|
||||
if payload.freqaimodel
|
||||
else config.get("freqaimodel"),
|
||||
"freqaimodel": (
|
||||
payload.freqaimodel if payload.freqaimodel else config.get("freqaimodel")
|
||||
),
|
||||
}
|
||||
)
|
||||
try:
|
||||
|
|
|
@ -148,9 +148,9 @@ class RPC:
|
|||
"bot_name": config.get("bot_name", "freqtrade"),
|
||||
"timeframe": config.get("timeframe"),
|
||||
"timeframe_ms": timeframe_to_msecs(config["timeframe"]) if "timeframe" in config else 0,
|
||||
"timeframe_min": timeframe_to_minutes(config["timeframe"])
|
||||
if "timeframe" in config
|
||||
else 0,
|
||||
"timeframe_min": (
|
||||
timeframe_to_minutes(config["timeframe"]) if "timeframe" in config else 0
|
||||
),
|
||||
"exchange": config["exchange"]["name"],
|
||||
"strategy": config["strategy"],
|
||||
"force_entry_enable": config.get("force_entry_enable", False),
|
||||
|
@ -404,11 +404,13 @@ class RPC:
|
|||
"abs_profit": value["amount"],
|
||||
"starting_balance": value["daily_stake"],
|
||||
"rel_profit": value["rel_profit"],
|
||||
"fiat_value": self._fiat_converter.convert_amount(
|
||||
value["amount"], stake_currency, fiat_display_currency
|
||||
)
|
||||
if self._fiat_converter
|
||||
else 0,
|
||||
"fiat_value": (
|
||||
self._fiat_converter.convert_amount(
|
||||
value["amount"], stake_currency, fiat_display_currency
|
||||
)
|
||||
if self._fiat_converter
|
||||
else 0
|
||||
),
|
||||
"trade_count": value["trades"],
|
||||
}
|
||||
for key, value in profit_units.items()
|
||||
|
|
|
@ -120,13 +120,13 @@ class RPCManager:
|
|||
self.send_msg(
|
||||
{
|
||||
"type": RPCMessageType.STARTUP,
|
||||
"status": f'*Exchange:* `{exchange_name}`\n'
|
||||
f'*Stake per trade:* `{stake_amount} {stake_currency}`\n'
|
||||
f'*Minimum ROI:* `{minimal_roi}`\n'
|
||||
f'*{"Trailing " if trailing_stop else ""}Stoploss:* `{stoploss}`\n'
|
||||
f'*Position adjustment:* `{pos_adjust_enabled}`\n'
|
||||
f'*Timeframe:* `{timeframe}`\n'
|
||||
f'*Strategy:* `{strategy_name}`',
|
||||
"status": f"*Exchange:* `{exchange_name}`\n"
|
||||
f"*Stake per trade:* `{stake_amount} {stake_currency}`\n"
|
||||
f"*Minimum ROI:* `{minimal_roi}`\n"
|
||||
f"*{'Trailing ' if trailing_stop else ''}Stoploss:* `{stoploss}`\n"
|
||||
f"*Position adjustment:* `{pos_adjust_enabled}`\n"
|
||||
f"*Timeframe:* `{timeframe}`\n"
|
||||
f"*Strategy:* `{strategy_name}`",
|
||||
}
|
||||
)
|
||||
self.send_msg(
|
||||
|
|
|
@ -729,9 +729,12 @@ class Telegram(RPCHandler):
|
|||
lines = [
|
||||
"*Trade ID:* `{trade_id}`" + (" `(since {open_date_hum})`" if r["is_open"] else ""),
|
||||
"*Current Pair:* {pair}",
|
||||
f"*Direction:* {'`Short`' if r.get('is_short') else '`Long`'}" + " ` ({leverage}x)`"
|
||||
if r.get("leverage")
|
||||
else "",
|
||||
(
|
||||
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 "",
|
||||
|
@ -753,9 +756,11 @@ class Telegram(RPCHandler):
|
|||
f"*Close Rate:* `{round_value(r['close_rate'], 8)}`" if r["close_rate"] else "",
|
||||
"*Open Date:* `{open_date}`",
|
||||
"*Close Date:* `{close_date}`" if r["close_date"] else "",
|
||||
f" \n*Current Rate:* `{round_value(r['current_rate'], 8)}`"
|
||||
if r["is_open"]
|
||||
else "",
|
||||
(
|
||||
f" \n*Current Rate:* `{round_value(r['current_rate'], 8)}`"
|
||||
if r["is_open"]
|
||||
else ""
|
||||
),
|
||||
("*Unrealized Profit:* " if r["is_open"] else "*Close Profit: *")
|
||||
+ "`{profit_ratio:.2%}` `({profit_abs_r})`",
|
||||
]
|
||||
|
@ -1072,15 +1077,19 @@ class Telegram(RPCHandler):
|
|||
[
|
||||
[
|
||||
"Wins",
|
||||
str(timedelta(seconds=durations["wins"]))
|
||||
if durations["wins"] is not None
|
||||
else "N/A",
|
||||
(
|
||||
str(timedelta(seconds=durations["wins"]))
|
||||
if durations["wins"] is not None
|
||||
else "N/A"
|
||||
),
|
||||
],
|
||||
[
|
||||
"Losses",
|
||||
str(timedelta(seconds=durations["losses"]))
|
||||
if durations["losses"] is not None
|
||||
else "N/A",
|
||||
(
|
||||
str(timedelta(seconds=durations["losses"]))
|
||||
if durations["losses"] is not None
|
||||
else "N/A"
|
||||
),
|
||||
],
|
||||
],
|
||||
headers=["", "Avg. Duration"],
|
||||
|
@ -1429,7 +1438,7 @@ class Telegram(RPCHandler):
|
|||
msg = self._rpc._rpc_delete(trade_id)
|
||||
await self._send_msg(
|
||||
f"`{msg['result_msg']}`\n"
|
||||
'Please make sure to take care of this asset on the exchange manually.'
|
||||
"Please make sure to take care of this asset on the exchange manually."
|
||||
)
|
||||
|
||||
@authorized_only
|
||||
|
|
|
@ -927,9 +927,11 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||
(
|
||||
p[0],
|
||||
p[1],
|
||||
CandleType.from_string(p[2])
|
||||
if len(p) > 2 and p[2] != ""
|
||||
else self.config.get("candle_type_def", CandleType.SPOT),
|
||||
(
|
||||
CandleType.from_string(p[2])
|
||||
if len(p) > 2 and p[2] != ""
|
||||
else self.config.get("candle_type_def", CandleType.SPOT)
|
||||
),
|
||||
)
|
||||
for p in informative_pairs
|
||||
]
|
||||
|
|
|
@ -693,7 +693,7 @@ def test_process_trade_creation(
|
|||
|
||||
assert log_has(
|
||||
f'{"Short" if is_short else "Long"} signal found: about create a new trade for ETH/USDT '
|
||||
'with stake_amount: 60.0 ...',
|
||||
"with stake_amount: 60.0 ...",
|
||||
caplog,
|
||||
)
|
||||
|
||||
|
|
|
@ -508,9 +508,9 @@ def test_min_roi_reached3(default_conf, fee) -> None:
|
|||
0.09,
|
||||
0.98,
|
||||
ExitType.NONE,
|
||||
lambda current_profit, **kwargs: -0.1
|
||||
if current_profit < 0.6
|
||||
else -(current_profit * 2),
|
||||
lambda current_profit, **kwargs: (
|
||||
-0.1 if current_profit < 0.6 else -(current_profit * 2)
|
||||
),
|
||||
),
|
||||
# Error case - static stoploss in place
|
||||
(
|
||||
|
|
|
@ -47,7 +47,8 @@ def test_strategy_updater_start(user_dir, capsys) -> None:
|
|||
|
||||
def test_strategy_updater_methods(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code1 = instance_strategy_updater.update_code("""
|
||||
modified_code1 = instance_strategy_updater.update_code(
|
||||
"""
|
||||
class testClass(IStrategy):
|
||||
def populate_buy_trend():
|
||||
pass
|
||||
|
@ -59,7 +60,8 @@ class testClass(IStrategy):
|
|||
pass
|
||||
def custom_sell():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "populate_entry_trend" in modified_code1
|
||||
assert "populate_exit_trend" in modified_code1
|
||||
|
@ -72,11 +74,13 @@ class testClass(IStrategy):
|
|||
def test_strategy_updater_params(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
|
||||
modified_code2 = instance_strategy_updater.update_code("""
|
||||
modified_code2 = instance_strategy_updater.update_code(
|
||||
"""
|
||||
ticker_interval = '15m'
|
||||
buy_some_parameter = IntParameter(space='buy')
|
||||
sell_some_parameter = IntParameter(space='sell')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "timeframe" in modified_code2
|
||||
# check for not editing hyperopt spaces
|
||||
|
@ -86,13 +90,15 @@ sell_some_parameter = IntParameter(space='sell')
|
|||
|
||||
def test_strategy_updater_constants(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code3 = instance_strategy_updater.update_code("""
|
||||
modified_code3 = instance_strategy_updater.update_code(
|
||||
"""
|
||||
use_sell_signal = True
|
||||
sell_profit_only = True
|
||||
sell_profit_offset = True
|
||||
ignore_roi_if_buy_signal = True
|
||||
forcebuy_enable = True
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "use_exit_signal" in modified_code3
|
||||
assert "exit_profit_only" in modified_code3
|
||||
|
@ -103,10 +109,12 @@ forcebuy_enable = True
|
|||
|
||||
def test_strategy_updater_df_columns(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
dataframe.loc[reduce(lambda x, y: x & y, conditions), ["buy", "buy_tag"]] = (1, "buy_signal_1")
|
||||
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "enter_long" in modified_code
|
||||
assert "exit_long" in modified_code
|
||||
|
@ -115,18 +123,21 @@ dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1
|
|||
|
||||
def test_strategy_updater_method_params(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
def confirm_trade_exit(sell_reason: str):
|
||||
nr_orders = trade.nr_of_successful_buys
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert "exit_reason" in modified_code
|
||||
assert "nr_orders = trade.nr_of_successful_entries" in modified_code
|
||||
|
||||
|
||||
def test_strategy_updater_dicts(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
order_time_in_force = {
|
||||
'buy': 'gtc',
|
||||
'sell': 'ioc'
|
||||
|
@ -141,7 +152,8 @@ unfilledtimeout = {
|
|||
'buy': 1,
|
||||
'sell': 2
|
||||
}
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "'entry': 'gtc'" in modified_code
|
||||
assert "'exit': 'ioc'" in modified_code
|
||||
|
@ -153,11 +165,13 @@ unfilledtimeout = {
|
|||
|
||||
def test_strategy_updater_comparisons(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
def confirm_trade_exit(sell_reason):
|
||||
if (sell_reason == 'stop_loss'):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert "exit_reason" in modified_code
|
||||
assert "exit_reason == 'stop_loss'" in modified_code
|
||||
|
||||
|
@ -165,11 +179,13 @@ def confirm_trade_exit(sell_reason):
|
|||
def test_strategy_updater_strings(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
sell_reason == 'sell_signal'
|
||||
sell_reason == 'force_sell'
|
||||
sell_reason == 'emergency_sell'
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
# those tests currently don't work, next in line.
|
||||
assert "exit_signal" in modified_code
|
||||
|
@ -180,7 +196,8 @@ sell_reason == 'emergency_sell'
|
|||
|
||||
def test_strategy_updater_comments(default_conf, caplog) -> None:
|
||||
instance_strategy_updater = StrategyUpdater()
|
||||
modified_code = instance_strategy_updater.update_code("""
|
||||
modified_code = instance_strategy_updater.update_code(
|
||||
"""
|
||||
# This is the 1st comment
|
||||
import talib.abstract as ta
|
||||
# This is the 2nd comment
|
||||
|
@ -197,7 +214,8 @@ class someStrategy(IStrategy):
|
|||
|
||||
# This is the 4th comment
|
||||
stoploss = -0.1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
assert "This is the 1st comment" in modified_code
|
||||
assert "This is the 2nd comment" in modified_code
|
||||
|
|
Loading…
Reference in New Issue
Block a user