freqtrade_origin/freqtrade/commands/list_commands.py

326 lines
11 KiB
Python
Raw Normal View History

import csv
import logging
import sys
from typing import Any, Union
import rapidjson
from rich.console import Console
from rich.table import Table
from rich.text import Text
from freqtrade.configuration import setup_utils_configuration
2021-06-08 19:20:35 +00:00
from freqtrade.enums import RunMode
2024-03-19 06:06:43 +00:00
from freqtrade.exceptions import ConfigurationError, OperationalException
2023-06-03 06:36:14 +00:00
from freqtrade.exchange import list_available_exchanges, market_is_active
2024-09-04 04:44:48 +00:00
from freqtrade.ft_types import ValidExchangesType
2021-07-12 12:08:01 +00:00
from freqtrade.misc import parse_db_uri_for_logging, plural
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
2024-07-06 16:26:36 +00:00
from freqtrade.util import print_rich_table
2020-09-28 17:39:41 +00:00
logger = logging.getLogger(__name__)
def start_list_exchanges(args: dict[str, Any]) -> None:
"""
Print available exchanges
:param args: Cli args from Arguments()
:return: None
"""
available_exchanges: list[ValidExchangesType] = list_available_exchanges(
args["list_exchanges_all"]
)
2021-04-06 05:47:44 +00:00
2024-05-12 14:27:03 +00:00
if args["print_one_column"]:
print("\n".join([e["classname"] for e in available_exchanges]))
else:
if args["list_exchanges_all"]:
title = (
f"All exchanges supported by the ccxt library "
f"({len(available_exchanges)} exchanges):"
)
else:
available_exchanges = [e for e in available_exchanges if e["valid"] is not False]
title = f"Exchanges available for Freqtrade ({len(available_exchanges)} exchanges):"
table = Table(title=title)
table.add_column("Exchange Name")
table.add_column("Class Name")
table.add_column("Markets")
table.add_column("Reason")
for exchange in available_exchanges:
name = Text(exchange["name"])
if exchange["supported"]:
name.append(" (Supported)", style="italic")
name.stylize("green bold")
classname = Text(exchange["classname"])
if exchange["is_alias"]:
name.stylize("strike")
classname.stylize("strike")
classname.append(f" (use {exchange['alias_for']})", style="italic")
trade_modes = Text(
", ".join(
(f"{a.get('margin_mode', '')} {a['trading_mode']}").lstrip()
for a in exchange["trade_modes"]
),
style="",
)
if exchange["dex"]:
trade_modes = Text("DEX: ") + trade_modes
trade_modes.stylize("bold", 0, 3)
2021-04-06 05:47:44 +00:00
table.add_row(
name,
classname,
trade_modes,
exchange["comment"],
style=None if exchange["valid"] else "red",
2024-05-12 14:27:03 +00:00
)
# table.add_row(*[exchange[header] for header in headers])
console = Console()
console.print(table)
def _print_objs_tabular(objs: list, print_colorized: bool) -> None:
2024-05-12 14:27:03 +00:00
names = [s["name"] for s in objs]
objs_to_print: list[dict[str, Union[Text, str]]] = [
2024-05-12 14:27:03 +00:00
{
"name": Text(s["name"] if s["name"] else "--"),
2024-07-07 06:36:51 +00:00
"location": s["location_rel"],
2024-05-12 14:27:03 +00:00
"status": (
Text("LOAD FAILED", style="bold red")
2024-05-12 14:27:03 +00:00
if s["class"] is None
else Text("OK", style="bold green")
2024-05-12 14:27:03 +00:00
if names.count(s["name"]) == 1
else Text("DUPLICATE NAME", style="bold yellow")
2024-05-12 14:27:03 +00:00
),
}
for s in objs
]
for idx, s in enumerate(objs):
2024-05-12 14:27:03 +00:00
if "hyperoptable" in s:
objs_to_print[idx].update(
{
"hyperoptable": "Yes" if s["hyperoptable"]["count"] > 0 else "No",
"buy-Params": str(len(s["hyperoptable"].get("buy", []))),
"sell-Params": str(len(s["hyperoptable"].get("sell", []))),
2024-05-12 14:27:03 +00:00
}
)
2024-07-07 06:36:51 +00:00
table = Table()
for header in objs_to_print[0].keys():
table.add_column(header.capitalize(), justify="right")
for row in objs_to_print:
table.add_row(*[row[header] for header in objs_to_print[0].keys()])
console = Console(
color_system="auto" if print_colorized else None,
width=200 if "pytest" in sys.modules else None,
)
console.print(table)
def start_list_strategies(args: dict[str, Any]) -> None:
"""
2020-02-02 15:48:29 +00:00
Print files with Strategy custom classes available in the directory
"""
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
strategy_objs = StrategyResolver.search_all_objects(
2024-05-12 14:27:03 +00:00
config, not args["print_one_column"], config.get("recursive_strategy_search", False)
)
# Sort alphabetically
2024-05-12 14:27:03 +00:00
strategy_objs = sorted(strategy_objs, key=lambda x: x["name"])
for obj in strategy_objs:
2024-05-12 14:27:03 +00:00
if obj["class"]:
obj["hyperoptable"] = obj["class"].detect_all_parameters()
else:
2024-05-12 14:27:03 +00:00
obj["hyperoptable"] = {"count": 0}
2024-05-12 14:27:03 +00:00
if args["print_one_column"]:
print("\n".join([s["name"] for s in strategy_objs]))
else:
2024-05-12 14:27:03 +00:00
_print_objs_tabular(strategy_objs, config.get("print_colorized", False))
def start_list_freqAI_models(args: dict[str, Any]) -> None:
2022-10-14 16:20:49 +00:00
"""
Print files with FreqAI models custom classes available in the directory
"""
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
from freqtrade.resolvers.freqaimodel_resolver import FreqaiModelResolver
2024-05-12 14:27:03 +00:00
model_objs = FreqaiModelResolver.search_all_objects(config, not args["print_one_column"])
2022-10-14 16:20:49 +00:00
# Sort alphabetically
2024-05-12 14:27:03 +00:00
model_objs = sorted(model_objs, key=lambda x: x["name"])
if args["print_one_column"]:
print("\n".join([s["name"] for s in model_objs]))
2022-10-14 16:20:49 +00:00
else:
2024-05-12 14:27:03 +00:00
_print_objs_tabular(model_objs, config.get("print_colorized", False))
2022-10-14 16:20:49 +00:00
def start_list_timeframes(args: dict[str, Any]) -> None:
"""
2021-04-03 14:54:47 +00:00
Print timeframes available on Exchange
"""
config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE)
# Do not use timeframe set in the config
2024-05-12 14:27:03 +00:00
config["timeframe"] = None
# Init exchange
2023-05-13 06:27:27 +00:00
exchange = ExchangeResolver.load_exchange(config, validate=False)
2024-05-12 14:27:03 +00:00
if args["print_one_column"]:
print("\n".join(exchange.timeframes))
else:
2024-05-12 14:27:03 +00:00
print(
f"Timeframes available for the exchange `{exchange.name}`: "
f"{', '.join(exchange.timeframes)}"
)
def start_list_markets(args: dict[str, Any], pairs_only: bool = False) -> None:
"""
Print pairs/markets on the exchange
:param args: Cli args from Arguments()
:param pairs_only: if True print only pairs, otherwise print all instruments (markets)
:return: None
"""
config = setup_utils_configuration(args, RunMode.UTIL_EXCHANGE)
# Init exchange
2023-05-13 06:27:27 +00:00
exchange = ExchangeResolver.load_exchange(config, validate=False)
# By default only active pairs/markets are to be shown
2024-05-12 14:27:03 +00:00
active_only = not args.get("list_pairs_all", False)
2024-05-12 14:27:03 +00:00
base_currencies = args.get("base_currencies", [])
quote_currencies = args.get("quote_currencies", [])
try:
2024-05-12 14:27:03 +00:00
pairs = exchange.get_markets(
base_currencies=base_currencies,
quote_currencies=quote_currencies,
tradable_only=pairs_only,
active_only=active_only,
)
# Sort the pairs/markets by symbol
pairs = dict(sorted(pairs.items()))
except Exception as e:
raise OperationalException(f"Cannot get markets. Reason: {e}") from e
else:
2024-05-12 14:27:03 +00:00
summary_str = (
(f"Exchange {exchange.name} has {len(pairs)} ")
+ ("active " if active_only else "")
+ (plural(len(pairs), "pair" if pairs_only else "market"))
+ (
f" with {', '.join(base_currencies)} as base "
f"{plural(len(base_currencies), 'currency', 'currencies')}"
if base_currencies
else ""
)
+ (" and" if base_currencies and quote_currencies else "")
+ (
f" with {', '.join(quote_currencies)} as quote "
f"{plural(len(quote_currencies), 'currency', 'currencies')}"
if quote_currencies
else ""
)
)
headers = [
"Id",
"Symbol",
"Base",
"Quote",
"Active",
"Spot",
"Margin",
"Future",
"Leverage",
]
tabular_data = [
{
"Id": v["id"],
"Symbol": v["symbol"],
"Base": v["base"],
"Quote": v["quote"],
"Active": market_is_active(v),
"Spot": "Spot" if exchange.market_is_spot(v) else "",
"Margin": "Margin" if exchange.market_is_margin(v) else "",
"Future": "Future" if exchange.market_is_future(v) else "",
"Leverage": exchange.get_max_leverage(v["symbol"], 20),
}
for _, v in pairs.items()
]
if (
args.get("print_one_column", False)
or args.get("list_pairs_print_json", False)
or args.get("print_csv", False)
):
# Print summary string in the log in case of machine-readable
# regular formats.
logger.info(f"{summary_str}.")
else:
# Print empty string separating leading logs and output in case of
# human-readable formats.
print()
if pairs:
2024-05-12 14:27:03 +00:00
if args.get("print_list", False):
# print data as a list, with human-readable summary
print(f"{summary_str}: {', '.join(pairs.keys())}.")
2024-05-12 14:27:03 +00:00
elif args.get("print_one_column", False):
print("\n".join(pairs.keys()))
elif args.get("list_pairs_print_json", False):
print(rapidjson.dumps(list(pairs.keys()), default=str))
2024-05-12 14:27:03 +00:00
elif args.get("print_csv", False):
writer = csv.DictWriter(sys.stdout, fieldnames=headers)
writer.writeheader()
writer.writerows(tabular_data)
else:
2024-07-06 16:30:48 +00:00
print_rich_table(tabular_data, headers, summary_str)
2024-05-12 14:27:03 +00:00
elif not (
args.get("print_one_column", False)
or args.get("list_pairs_print_json", False)
or args.get("print_csv", False)
):
print(f"{summary_str}.")
2020-05-02 09:26:12 +00:00
def start_show_trades(args: dict[str, Any]) -> None:
2020-05-02 09:26:12 +00:00
"""
Show trades
"""
import json
2020-09-28 17:39:41 +00:00
2020-10-16 05:39:12 +00:00
from freqtrade.persistence import Trade, init_db
2024-05-12 14:27:03 +00:00
2020-05-02 09:26:12 +00:00
config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)
2024-05-12 14:27:03 +00:00
if "db_url" not in config:
2024-03-19 06:06:43 +00:00
raise ConfigurationError("--db-url is required for this command.")
2021-07-12 12:08:01 +00:00
logger.info(f'Using DB: "{parse_db_uri_for_logging(config["db_url"])}"')
2024-05-12 14:27:03 +00:00
init_db(config["db_url"])
2020-05-02 09:26:12 +00:00
tfilter = []
2024-05-12 14:27:03 +00:00
if config.get("trade_ids"):
tfilter.append(Trade.id.in_(config["trade_ids"]))
2020-05-02 09:26:12 +00:00
2020-05-02 09:44:18 +00:00
trades = Trade.get_trades(tfilter).all()
logger.info(f"Printing {len(trades)} Trades: ")
2024-05-12 14:27:03 +00:00
if config.get("print_json", False):
2020-05-02 09:26:12 +00:00
print(json.dumps([trade.to_json() for trade in trades], indent=4))
else:
for trade in trades:
print(trade)