freqtrade_origin/freqtrade/commands/list_commands.py

326 lines
11 KiB
Python
Raw Normal View History

import csv
import logging
import sys
2024-07-07 06:36:51 +00:00
from typing import Any, Dict, List, 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)
2022-10-14 14:32:30 +00:00
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]
2024-07-07 06:36:51 +00:00
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))
2022-10-14 16:20:49 +00:00
def start_list_freqAI_models(args: Dict[str, Any]) -> None:
"""
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:
"""
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)