diff --git a/freqtrade/rpc/local_rest_server.py b/freqtrade/rpc/local_rest_server.py
index 0c9fad16b..24d9a6594 100644
--- a/freqtrade/rpc/local_rest_server.py
+++ b/freqtrade/rpc/local_rest_server.py
@@ -5,43 +5,11 @@ import json
from flask import Flask, request
from flask_restful import Resource, Api
from json import dumps
-from freqtrade.rpc.rpc import RPC
+from freqtrade.rpc.rpc import RPC, RPCException
logger = logging.getLogger(__name__)
-
-class Daily(Resource):
- # called by http://127.0.0.1:/daily?timescale=7
- # where 7 is the number of days to report back with
-
- def __init__(self, freqtrade) -> None:
- """
- Initializes all enabled rpc modules
- :param freqtrade: Instance of a freqtrade bot
- :return: None
- """
- self.freqtrade = freqtrade
- self._config = freqtrade.config
-
-
- def get(self):
- timescale = request.args.get('timescale')
- logger.info("LocalRPC - Daily Command Called")
- timescale = int(timescale)
-
- (error, stats) = RPC.rpc_daily_profit(self, timescale,
- self._config['stake_currency'],
- self._config['fiat_display_currency']
- )
- if error == False:
- stats = dumps(stats, indent=4, sort_keys=True, default=str)
- return stats
- else:
- json.dumps(error)
- return error
-
-
class LocalRestSuperWrap(RPC):
"""
This class is for REST cmd line client
@@ -61,23 +29,85 @@ class LocalRestSuperWrap(RPC):
thread = threading.Thread(target=self.run, args=(freqtrade,)) # extra comma as ref ! Tuple
thread.daemon = True # Daemonize thread
- thread.start() # Start the execution
+ thread.start() # Start the execution
+
def run(self, freqtrade):
""" Method that runs forever """
self._config = freqtrade.config
-
-
- # TODO add IP address / port to bind to in config.json and use in below.
- logger.info('Starting Local Rest Server')
-
- my_freqtrade = freqtrade
app = Flask(__name__)
- api = Api(app)
- # Our resources for restful apps go here, pass freqtrade object across
- api.add_resource(Daily, '/daily', methods=['GET'],
- resource_class_kwargs={'freqtrade': my_freqtrade}) # Route for returning daily
+ """
+ Define the application routes here
+ each Telegram command should have a like local substitute
+ """
+ @app.route("/")
+ def hello():
+ # For simple rest server testing via browser
+ # cmds = 'Try uri:/daily?timescale=7 /profit /balance /status
+ # /status /table /performance /count,
+ # /start /stop /help'
- #run the server
- app.run(port='5002')
+ rest_cmds ='Commands implemented:
' \
+ '/daily?timescale=7' \
+ '
' \
+ '/stop' \
+ '
' \
+ '/start'
+ return rest_cmds
+
+ @app.route('/daily', methods=['GET'])
+ def daily():
+ try:
+ timescale = request.args.get('timescale')
+ logger.info("LocalRPC - Daily Command Called")
+ timescale = int(timescale)
+
+ stats = self._rpc_daily_profit(timescale,
+ self._config['stake_currency'],
+ self._config['fiat_display_currency']
+ )
+
+ stats = dumps(stats, indent=4, sort_keys=True, default=str)
+ return stats
+ except RPCException as e:
+ return e
+
+ @app.route('/start', methods=['GET'])
+ def start():
+ """
+ Handler for /start.
+ Starts TradeThread
+ """
+ msg = self._rpc_start()
+ print("msg is", msg)
+ return msg
+
+ @app.route('/stop', methods=['GET'])
+ def stop():
+ """
+ Handler for /stop.
+ Stops TradeThread
+ """
+ msg = self._rpc_stop()
+ print("msg is", msg)
+ return msg
+
+ """
+ Section to handle configuration and running of the Rest serve
+ also to check and warn if not bound to 127.0.0.1 as a security risk
+ """
+
+ rest_ip = self._config['rest_cmd_line']['listen_ip_address']
+ rest_port = self._config['rest_cmd_line']['listen_port']
+
+ if rest_ip != "127.0.0.1":
+ i=0
+ while i < 10:
+ logger.info("SECURITY WARNING - Local Rest Server listening to external connections")
+ logger.info("SECURITY WARNING - This is insecure please set to 127.0.0.1 in config.json")
+ i += 1
+
+ # Run the Server
+ logger.info('Starting Local Rest Server')
+ app.run(host=rest_ip, port=rest_port)
diff --git a/freqtrade/rpc/rest_client.py b/freqtrade/rpc/rest_client.py
index 928e1798c..c5007970f 100755
--- a/freqtrade/rpc/rest_client.py
+++ b/freqtrade/rpc/rest_client.py
@@ -4,12 +4,20 @@ Simple command line client into RPC commands
Can be used as an alternate to Telegram
"""
+import time
from requests import get
from sys import argv
+
+
+#TODO - use argparse to clean this up
+#TODO - use IP and Port from config.json not hardcode
+
if len(argv) == 1:
print('\nThis script accepts the following arguments')
print('- daily (int) - Where int is the number of days to report back. daily 3')
+ print('- start - this will start the trading thread')
+ print('- stop - this will start the trading thread')
print('- there will be more....\n')
if len(argv) == 3 and argv[1] == "daily":
@@ -20,4 +28,26 @@ if len(argv) == 3 and argv[1] == "daily":
else:
print("\nThe second argument to daily must be an integer, 1,2,3 etc")
+if len(argv) == 2 and argv[1] == "start":
+ get_url = 'http://localhost:5002/start'
+ d = get(get_url).text
+ print(d)
+
+ if "already" not in d:
+ time.sleep(2)
+ d = get(get_url).text
+ print(d)
+
+if len(argv) == 2 and argv[1] == "stop":
+ get_url = 'http://localhost:5002/stop'
+ d = get(get_url).text
+ print(d)
+
+ if "already" not in d:
+ time.sleep(2)
+ d = get(get_url).text
+ print(d)
+
+
+
diff --git a/freqtrade/rpc/rpc_manager.py b/freqtrade/rpc/rpc_manager.py
index ef71ff3a9..21e54f488 100644
--- a/freqtrade/rpc/rpc_manager.py
+++ b/freqtrade/rpc/rpc_manager.py
@@ -1,13 +1,10 @@
"""
-This module contains class to manage RPC communications (Telegram, Slack, ....)
+This module contains class to manage RPC communications (Telegram, Slack, Rest ...)
"""
-from typing import Any, List
import logging
-import time
-
-from freqtrade.rpc.telegram import Telegram
-from freqtrade.rpc.local_rest_server import LocalRestSuperWrap
+from typing import List
+from freqtrade.rpc.rpc import RPC
logger = logging.getLogger(__name__)
@@ -17,42 +14,29 @@ class RPCManager(object):
Class to manage RPC objects (Telegram, Slack, ...)
"""
def __init__(self, freqtrade) -> None:
- """
- Initializes all enabled rpc modules
- :param config: config to use
- :return: None
- """
- self.freqtrade = freqtrade
+ """ Initializes all enabled rpc modules """
+ self.registered_modules: List[RPC] = []
- self.registered_modules: List[str] = []
- self.telegram: Any = None
- self._init()
-
- def _init(self) -> None:
- """
- Init RPC modules
- :return:
- """
- if self.freqtrade.config['telegram'].get('enabled', False):
+ # Enable telegram
+ if freqtrade.config['telegram'].get('enabled', False):
logger.info('Enabling rpc.telegram ...')
- self.registered_modules.append('telegram')
- self.telegram = Telegram(self.freqtrade)
+ from freqtrade.rpc.telegram import Telegram
+ self.registered_modules.append(Telegram(freqtrade))
- # Added another RPC client - for cmdline local client.
- # Uses existing superclass RPC build for Telegram
- if self.freqtrade.config['rest_cmd'].get('enabled', False):
- self.localRPC = LocalRestSuperWrap(self.freqtrade)
- time.sleep(1)
+ # Enable local rest server for cmd line control
+ if freqtrade.config['rest_cmd_line'].get('enabled', False):
+ logger.info('Enabling rpc.local_rest_server ...')
+ from freqtrade.rpc.local_rest_server import LocalRestSuperWrap
+ self.registered_modules.append(LocalRestSuperWrap(freqtrade))
def cleanup(self) -> None:
- """
- Stops all enabled rpc modules
- :return: None
- """
- if 'telegram' in self.registered_modules:
- logger.info('Cleaning up rpc.telegram ...')
- self.registered_modules.remove('telegram')
- self.telegram.cleanup()
+ """ Stops all enabled rpc modules """
+ logger.info('Cleaning up rpc modules ...')
+ while self.registered_modules:
+ mod = self.registered_modules.pop()
+ logger.debug('Cleaning up rpc.%s ...', mod.name)
+ mod.cleanup()
+ del mod
def send_msg(self, msg: str) -> None:
"""
@@ -60,6 +44,7 @@ class RPCManager(object):
:param msg: message
:return: None
"""
- logger.info(msg)
- if 'telegram' in self.registered_modules:
- self.telegram.send_msg(msg)
+ logger.info('Sending rpc message: %s', msg)
+ for mod in self.registered_modules:
+ logger.debug('Forwarding message to rpc.%s', mod.name)
+ mod.send_msg(msg)