freqtrade_origin/freqtrade/commands/list_commands.py

311 lines
11 KiB
Python
Raw Normal View History

import csv
import logging
import sys
from typing import Any, Dict, List, Union
import rapidjson
2020-09-28 17:39:41 +00:00
from colorama import Fore, Style
from colorama import init as colorama_init
from tabulate import tabulate
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
2021-07-12 12:08:01 +00:00
from freqtrade.misc import parse_db_uri_for_logging, plural
from freqtrade.resolvers import ExchangeResolver, StrategyResolver
from freqtrade.types import ValidExchangesType
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
"""
2024-05-12 14:27:03 +00:00
exchanges = 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["name"] for e in exchanges]))
else:
headers = {
2024-05-12 14:27:03 +00:00
"name": "Exchange name",
"supported": "Supported",
"trade_modes": "Markets",
"comment": "Reason",
}
headers.update({"valid": "Valid"} if args["list_exchanges_all"] else {})
def build_entry(exchange: ValidExchangesType, valid: bool):
2024-05-12 14:27:03 +00:00
valid_entry = {"valid": exchange["valid"]} if valid else {}
result: Dict[str, Union[str, bool]] = {
2024-05-12 14:27:03 +00:00
"name": exchange["name"],
**valid_entry,
2024-05-12 14:27:03 +00:00
"supported": "Official" if exchange["supported"] else "",
"trade_modes": ("DEX: " if exchange["dex"] else "")
+ ", ".join(
2024-05-12 14:27:03 +00:00
(f"{a['margin_mode']} " if a["margin_mode"] else "") + a["trading_mode"]
for a in exchange["trade_modes"]
),
2024-05-12 14:27:03 +00:00
"comment": exchange["comment"],
}
return result
2024-05-12 14:27:03 +00:00
if args["list_exchanges_all"]:
exchanges = [build_entry(e, True) for e in exchanges]
print(f"All exchanges supported by the ccxt library ({len(exchanges)} exchanges):")
else:
2024-05-12 14:27:03 +00:00
exchanges = [build_entry(e, False) for e in exchanges if e["valid"] is not False]
print(f"Exchanges available for Freqtrade ({len(exchanges)} exchanges):")
2021-04-06 05:47:44 +00:00
2024-05-12 14:27:03 +00:00
print(
tabulate(
exchanges,
headers=headers,
)
)
2022-10-14 14:32:30 +00:00
def _print_objs_tabular(objs: List, print_colorized: bool) -> None:
2020-02-14 19:28:49 +00:00
if print_colorized:
colorama_init(autoreset=True)
2020-02-15 17:43:11 +00:00
red = Fore.RED
yellow = Fore.YELLOW
reset = Style.RESET_ALL
else:
2024-05-12 14:27:03 +00:00
red = ""
yellow = ""
reset = ""
names = [s["name"] for s in objs]
objs_to_print = [
{
"name": s["name"] if s["name"] else "--",
"location": s["location_rel"],
"status": (
red + "LOAD FAILED" + reset
if s["class"] is None
else "OK"
if names.count(s["name"]) == 1
else yellow + "DUPLICATE NAME" + reset
),
}
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": len(s["hyperoptable"].get("buy", [])),
"sell-Params": len(s["hyperoptable"].get("sell", [])),
}
)
print(tabulate(objs_to_print, headers="keys", tablefmt="psql", stralign="right"))
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:
# print data as a table, with the human-readable summary
print(f"{summary_str}:")
2024-05-12 14:27:03 +00:00
print(tabulate(tabular_data, headers="keys", tablefmt="psql", stralign="right"))
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)