mirror of
https://github.com/Rikj000/MoniGoMani.git
synced 2022-03-06 00:08:05 +03:00
254 lines
10 KiB
Python
254 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
# -* vim: syntax=python -*-
|
|
|
|
# --- ↑↓ Do not remove these libs ↑↓ -----------------------------------------------------------------------------------
|
|
|
|
"""FreqtradeCli is the module responsible for all Freqtrade related tasks."""
|
|
|
|
# ______ _ _ _____ _ _
|
|
# | ___| | | | | / __ \| |(_)
|
|
# | |_ _ __ ___ __ _ | |_ _ __ __ _ __| | ___ | / \/| | _
|
|
# | _| | '__| / _ \ / _` || __|| '__| / _` | / _` | / _ \| | | || |
|
|
# | | | | | __/| (_| || |_ | | | (_| || (_| || __/| \__/\| || |
|
|
# \_| |_| \___| \__, | \__||_| \__,_| \__,_| \___| \____/|_||_|
|
|
# | |
|
|
# |_|
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
|
|
from pygit2 import Repository, clone_repository
|
|
from yaspin import yaspin
|
|
|
|
from user_data.mgm_tools.mgm_hurry.MoniGoManiCli import MoniGoManiCli
|
|
from user_data.mgm_tools.mgm_hurry.MoniGoManiConfig import MoniGoManiConfig
|
|
from user_data.mgm_tools.mgm_hurry.MoniGoManiLogger import MoniGoManiLogger
|
|
|
|
|
|
# --- ↑ Do not remove these libs ↑ -------------------------------------------------------------------------------------
|
|
|
|
YASPIN_INSTANCE: yaspin = None # Global scope for a reason
|
|
GIT_URL_FREQTRADE: str = 'https://github.com/freqtrade/freqtrade'
|
|
|
|
|
|
class FreqtradeCli:
|
|
"""
|
|
FreqtradeCli is responsible for all Freqtrade (installation) related tasks.
|
|
|
|
Attributes:
|
|
basedir The basedir where the monigomani install lives.
|
|
freqtrade_binary The abs path to the Freqtrade executable.
|
|
cli_logger The logger function of the MoniGoManiCli module.
|
|
monigomani_cli The MoniGoManiCli object.
|
|
monigomani_config The MoniGoManiConfig object.
|
|
_install_type The current install type of Freqtrade. Either 'source' or default 'docker'
|
|
"""
|
|
basedir: str
|
|
freqtrade_binary: str
|
|
cli_logger: MoniGoManiLogger
|
|
monigomani_cli: MoniGoManiCli
|
|
monigomani_config: MoniGoManiConfig
|
|
_install_type: str
|
|
|
|
def __init__(self, basedir: str):
|
|
"""Initialize the Freqtrade binary.
|
|
|
|
:param basedir: (str) The basedir to be used as our root directory.
|
|
"""
|
|
self.basedir = basedir
|
|
|
|
self.cli_logger = MoniGoManiLogger(self.basedir).get_logger()
|
|
self.monigomani_config = MoniGoManiConfig(self.basedir)
|
|
|
|
self._install_type = self.monigomani_config.get('install_type') or None
|
|
self.freqtrade_binary = self.monigomani_config.get('ft_binary') or None
|
|
|
|
self._init_freqtrade()
|
|
|
|
self.monigomani_cli = MoniGoManiCli(self.basedir)
|
|
|
|
def _init_freqtrade(self) -> bool:
|
|
"""
|
|
Initialize self.freqtrade_binary property.
|
|
|
|
:return bool: True if Freqtrade installation is found and property is set. False otherwise.
|
|
"""
|
|
if self.installation_exists() is False:
|
|
self.cli_logger.warning('🤷 No Freqtrade installation found.')
|
|
# ToDo
|
|
return False
|
|
|
|
self.freqtrade_binary = self._get_freqtrade_binary_path(self.basedir, self.install_type)
|
|
|
|
self.cli_logger.debug('👉 Freqtrade binary: `{0}`'.format(self.freqtrade_binary))
|
|
|
|
return True
|
|
|
|
@property
|
|
def install_type(self) -> str:
|
|
"""
|
|
Return property install_type.
|
|
|
|
:return str: The install type. either source, docker or None.
|
|
"""
|
|
return self._install_type
|
|
|
|
@install_type.setter
|
|
def install_type(self, p_install_type):
|
|
if p_install_type in {'source', 'docker'}:
|
|
self._install_type = p_install_type
|
|
|
|
def logger(self) -> MoniGoManiLogger:
|
|
"""
|
|
Access the internal logger.
|
|
|
|
:return logger: (MoniGoManiLogger) Current internal logger.
|
|
"""
|
|
return self.cli_logger
|
|
|
|
def installation_exists(self) -> bool:
|
|
"""Return true if all is setup correctly.
|
|
|
|
:return bool: True if install_type is docker or Freqtrade is found. False otherwise.
|
|
"""
|
|
if self.install_type is None:
|
|
self.cli_logger.warning('FreqtradeCli - installation_exists() failed. No install_type.')
|
|
return False
|
|
|
|
# Well if install_type is docker, we return True because we don't verify if docker is installed
|
|
if self.install_type == 'docker':
|
|
self.cli_logger.debug(
|
|
'FreqtradeCli - installation_exists() succeeded because install_type is set to docker.')
|
|
return True
|
|
|
|
if self.freqtrade_binary is None:
|
|
self.cli_logger.warning('FreqtradeCli - installation_exists() failed. No freqtrade_binary.')
|
|
return False
|
|
|
|
if self.install_type == 'source':
|
|
self.cli_logger.debug('FreqtradeCli - installation_exists() install_type is "source".')
|
|
if os.path.exists('{0}/.env/bin/freqtrade'.format(self.basedir)):
|
|
return True
|
|
|
|
self.cli_logger.warning('FreqtradeCli - installation_exists() failed. '
|
|
'Freqtrade binary not found in {0}/.env/bin/freqtrade.'.format(self.basedir))
|
|
|
|
return False
|
|
|
|
def download_setup_freqtrade(self, branch: str = 'develop', target_dir: str = None) -> bool:
|
|
"""
|
|
Install Freqtrade using a git clone to target_dir.
|
|
|
|
:param branch: (str) Checkout a specific branch. Defaults to 'develop'.
|
|
:param target_dir: (str) Specify a target_dir to install Freqtrade. Defaults to os.getcwd().
|
|
:return bool: True if setup completed without errors, else False.
|
|
"""
|
|
with tempfile.TemporaryDirectory() as temp_dirname:
|
|
with yaspin(text='👉 Clone Freqtrade repository', color='cyan') as sp:
|
|
repo = clone_repository(GIT_URL_FREQTRADE, temp_dirname, checkout_branch=branch)
|
|
|
|
if not isinstance(repo, Repository):
|
|
sp.red.write('😕 Failed to clone Freqtrade repo. I quit!')
|
|
self.cli_logger.critical('😕 Failed to clone Freqtrade repo. I quit!')
|
|
sys.exit(1)
|
|
|
|
sp.green.ok('✔')
|
|
|
|
with yaspin(text='👉 Copy Freqtrade installation', color='cyan') as sp:
|
|
self.copy_installation_files(temp_dirname, target_dir)
|
|
sp.green.ok('✔')
|
|
|
|
with yaspin(text='', color='cyan') as sp:
|
|
sp.write('👉 Run Freqtrade setup')
|
|
|
|
# Hide the spinner as the Freqtrade installer asks for user input.
|
|
with sp.hidden():
|
|
result = self.run_setup_installer(target_dir)
|
|
|
|
if result is True:
|
|
sp.green.ok('✔ Freqtrade setup completed')
|
|
return True
|
|
|
|
sp.red.write('😕 Freqtrade setup failed')
|
|
return False
|
|
|
|
def copy_installation_files(self, temp_dirname: str, target_dir: str):
|
|
"""
|
|
Copy the installation files to the target directory. Also symlink the 'setup.exp' file.
|
|
|
|
:param temp_dirname: (str) The source directory where installation files exist.
|
|
:param target_dir: (str) The target directory where the installation files should be copied to.
|
|
"""
|
|
if not os.path.exists(target_dir):
|
|
os.makedirs(target_dir, exist_ok=True)
|
|
|
|
self.monigomani_cli.run_command('cp -rT {0} {1}'.format(temp_dirname, target_dir))
|
|
|
|
if not os.path.isfile(f'{target_dir}/monigomani/setup.exp'):
|
|
self.cli_logger.error('🤷 No "setup.exp" found, back to the MoniGoMani installation docs it is!')
|
|
sys.exit(1)
|
|
os.symlink(f'{target_dir}/monigomani/setup.exp', f'{target_dir}/setup.exp')
|
|
|
|
def run_setup_installer(self, target_dir: str) -> bool:
|
|
"""
|
|
Run Freqtrade setup.sh --install through setup.exp
|
|
|
|
:param target_dir: (str) The target directory where Freqtrade is installed.
|
|
:return bool: True if setup ran successfully. False otherwise.
|
|
"""
|
|
|
|
if os.path.isfile('{0}/setup.exp'.format(target_dir)):
|
|
# Using 'except' to automatically skip resetting the git repo, but do install all dependencies
|
|
self.monigomani_cli.run_command('{0}/setup.exp'.format(target_dir))
|
|
return True
|
|
|
|
self.cli_logger.error('Could not run {0}/setup.exp for Freqtrade because the file does not exist.'
|
|
.format(target_dir))
|
|
|
|
return False
|
|
|
|
def download_static_pairlist(self, stake_currency: str, exchange: str) -> dict:
|
|
"""
|
|
Use Freqtrade test-pairlist command to download and test valid pair whitelist.
|
|
|
|
:param stake_currency: (str) The stake currency to find the list of. Eg. BTC
|
|
:param exchange: (str) The exchange to read the data from. Eg. Binance
|
|
:return dict: The static pair whitelist as a dictionary.
|
|
"""
|
|
with tempfile.NamedTemporaryFile() as temp_file:
|
|
self.monigomani_cli.run_command(
|
|
('source ./.env/bin/activate; '
|
|
'freqtrade test-pairlist -c {0}/user_data/mgm_tools/{1}-Retrieve-Top-Volume-StaticPairList.json '
|
|
'--quote {2} --print-json > {3}'
|
|
.format(self.basedir, exchange.title(), stake_currency, temp_file.name)))
|
|
|
|
# Read last line from temp_file, which is the json list containing pairlists
|
|
try:
|
|
last_line = subprocess.check_output(['tail', '-1', temp_file.name])
|
|
pair_whitelist = json.loads(last_line)
|
|
except json.JSONDecodeError as e:
|
|
self.cli_logger.critical('Unfortunately we could generate the static pairlist.')
|
|
self.cli_logger.debug(e)
|
|
return False
|
|
|
|
return pair_whitelist
|
|
|
|
@staticmethod
|
|
def _get_freqtrade_binary_path(basedir: str, install_type: str):
|
|
"""
|
|
Determine the Freqtrade binary path based on install_type.
|
|
|
|
:param basedir: (str) Basedir is used in case of source installation
|
|
:param install_type: (str) Either docker or source.
|
|
:return str: Command to run Freqtrade. Defaults to docker.
|
|
"""
|
|
freqtrade_binary = 'docker-compose run --rm freqtrade'
|
|
|
|
if install_type == 'source':
|
|
freqtrade_binary = 'source {0}/.env/bin/activate; freqtrade'.format(basedir)
|
|
|
|
return freqtrade_binary
|