def __init__(self, trades_path, completed_trades_path, config_path, enable_cloud=False): super().__init__() self.trades_path = trades_path self.completed_trades_path = completed_trades_path self.config_path = config_path self.config_loader = ConfigLoader() self.trade_handler: TradeHandler = None self.fx = None self.file_watch_list = {} self.file_watch_timer = None self.lock = RLock() self.enable_cloud = enable_cloud self.s3pers: S3Persistence = None self.ignore_local_file_update = os.environ.get('IGNORE_FILE_UPDATE', False) if self.ignore_local_file_update: self.logInfo("IGNORE_FILE_UPDATE Enabled") if enable_cloud: self.s3pers: S3Persistence = S3Persistence( os.getenv('TRADE_BUCKET'), { trades_path: 'Portfolio/', completed_trades_path: 'Completed/' })
def test_change_order(): cl = ConfigLoader() orders = cl.load_trade_list(cl.json_loader('trades.json')) # orders[0].get_available_targets()[0].set_completed() # orders[0].status = OrderStatus.COMPLETED cl.save_trades(cl.json_saver('trades2.json'), orders) orders = cl.load_trade_list(cl.json_loader('trades2.json'))
def save_new_order_file_structure(path, new_path): target_path_list = [ f for f in listdir(path) if isfile(join(path, f)) and f.lower().endswith('json') ] for t_path in target_path_list: cl = ConfigLoader() o_loader = cl.json_loader(join(path, t_path)) trades = cl.load_trade_list(o_loader) for t in trades: if t.is_completed(): continue new_trade_path = new_path + t.symbol + '.json' cl.save_trades(cl.json_saver(new_trade_path), [t])
def generate_targets(start_price, iter=4, increment=4, smart=True, sl_interval=3): targets = [] prices = [] for i in range(0, iter): prices.append(start_price) vol = round(100 / (iter - i), 2) target = Target(price=start_price, vol='{}%'.format(vol), smart=smart) if sl_interval != 0 and len(prices) >= sl_interval: target.sl = prices[-sl_interval] targets.append(target) start_price = round(start_price * (1 + increment / 100), 8) print(ConfigLoader.get_json_str(targets))
def post(self, id=None): args = self.parser.parse_args() action = args['action'] if not action: return APIResult.ErrorResult(100, msg='No "action" was provided'), 403 strategies = self.get_strategies(id) if not strategies and id != '0': return APIResult.ErrorResult(101, msg='No strategies were found'), 404 action = action.lower() if action == 'close': for strategy in strategies: strategy.emergent_close_position() elif action in ['pause', 'resume']: paused = True if action == 'pause' else False for strategy in strategies: strategy.paused = paused elif action == 'add': ids = [] try: trade_json = args['data'] trades = ConfigLoader.load_trade_list_from_obj(trade_json) for trade in trades: ids.append(trade.id) self.th.updated_trade(trade) self.th.fire_trade_updated(trade, True) except Exception as e: self.th.logger.error(traceback.format_exc()) return json.dumps(APIResult.ErrorResult(100, str(e))), 500 return APIResult.OKResult(ids), 201 return APIResult.OKResult(), 200
class ConsoleLauncher(Logger): TRADE_FILE_PATH_PATTERN = '{path}{time}{symbol}.json' def __init__(self, trades_path, completed_trades_path, config_path, enable_cloud=False): super().__init__() self.trades_path = trades_path self.completed_trades_path = completed_trades_path self.config_path = config_path self.config_loader = ConfigLoader() self.trade_handler: TradeHandler = None self.fx = None self.file_watch_list = {} self.file_watch_timer = None self.lock = RLock() self.enable_cloud = enable_cloud self.s3pers: S3Persistence = None self.ignore_local_file_update = os.environ.get('IGNORE_FILE_UPDATE', False) if self.ignore_local_file_update: self.logInfo("IGNORE_FILE_UPDATE Enabled") if enable_cloud: self.s3pers: S3Persistence = S3Persistence( os.getenv('TRADE_BUCKET'), { trades_path: 'Portfolio/', completed_trades_path: 'Completed/' }) def start_bot(self): self.sync_down() # trade_loader = self.config_loader.advanced_loader(self.trades_path) trades = self.config_loader.load_trade_list(self.trades_path) trade_validator = TradeValidator() self.logInfo('Starting Bot... Version: {}'.format(BOT_VERSION)) for trade in trades[:]: if trade.is_completed() or trade.is_removed(): self.move_completed_trade(trade) if not trade_validator.validate(trade): self.logError('{}:{}'.format(trade.symbol, trade_validator.errors)) if len(trade_validator.warnings) > 0: self.logInfo('{}:{}'.format(trade.symbol, trade_validator.warnings)) trades.remove(trade) api_path = os.path.join(self.config_path, 'api.json') key, secret = self.get_exchange_creds(api_path) self.fx = FXConnector(key, secret, Utils.is_simulation()) self.trade_handler = TradeHandler( trades, self.fx, lambda trade, cloud_sync: self.on_trade_updated_by_handler( trade, cloud_sync)) self.init_file_watch_list() self.trade_handler.add_trades(trades) # self.trade_handler.init_strategies() # self.trade_handler.start_listening() self.start_timer() def get_exchange_creds(self, api_path): key = None secret = None if os.environ.get('KEY') and os.environ.get('SECRET'): key = os.environ.get('KEY') secret = os.environ.get('SECRET') elif os.path.exists(api_path): api = self.config_loader.json_loader( os.path.join(self.config_path, 'api.json'))() exchanges = [ ex for ex in api['exchanges'] if ex['name'].lower() == 'binance' ] if len(exchanges) > 0: api = exchanges[0] key = api['key'] secret = api['secret'] if not key or not secret: raise ValueError('API Key and Secret are not provided') return key, secret def sync_down(self): if self.enable_cloud: self.s3pers.sync(False, True) self.s3pers.finish() def init_file_watch_list(self): target_path_list = [ f for f in listdir(self.trades_path) if isfile(join(self.trades_path, f)) and f.lower().endswith('json') ] for trade_path in target_path_list: file = join(self.trades_path, trade_path) self.file_watch_list[file] = os.stat(file).st_mtime def stop_bot(self): if self.trade_handler: self.trade_handler.stop_listening() self.stop_timer() def start_timer(self): self.file_watch_timer = Timer(5, self.check_files_changed) self.file_watch_timer.name = 'Filewatch Timer' self.file_watch_timer.start() def stop_timer(self): if self.file_watch_timer: self.file_watch_timer.cancel() self.file_watch_timer = None def check_files_changed(self): try: deleted_by_s3, updated_by_s3 = set(), set() if self.enable_cloud: deleted_by_s3, updated_by_s3 = self.s3pers.check_s3_events() with self.lock: target_path_dict = { join(self.trades_path, f): os.stat(join(self.trades_path, f)).st_mtime for f in listdir(self.trades_path) if isfile(join(self.trades_path, f)) and f.lower().endswith('json') } removed_files = set(self.file_watch_list.keys()) - set( target_path_dict.keys()) update_cloud_files = False if removed_files: for file in removed_files: sym, trade_id = Utils.get_symbol_and_id_from_file_path( file) if trade_id: self.trade_handler.remove_trade_by_id(trade_id) else: self.logError('Can\'t remove trade {}'.format(file)) # else: # self.trade_handler.remove_trade_by_symbol(sym) self.file_watch_list.pop(file, None) if file not in deleted_by_s3: update_cloud_files = True for file, current_mtime in target_path_dict.items(): if file in self.file_watch_list: if not self.file_watch_list[file] == current_mtime: if self.ignore_local_file_update: self.logInfo( 'Ignoring file "{}" update.'.format(file)) self.logInfo( 'Current|Last file-change time {}|{}'.format( current_mtime, self.file_watch_list[file])) else: self.logInfo( 'File "{}" has changed. Updating trades...'. format(file)) trades = self.config_loader.load_trade_list(file) for t in trades: self.trade_handler.updated_trade(t) if file not in updated_by_s3: update_cloud_files = True self.file_watch_list[file] = os.stat(file).st_mtime else: self.logInfo( 'New file detected "{}". Updating trades...'.format( file)) update_cloud_files = True trades = self.config_loader.load_trade_list(file) for t in trades: #if file needs to be adjusted to the new format new_file_name = os.path.join( self.trades_path, Utils.get_file_name(t.symbol, t.id)) if new_file_name != file: self.file_watch_list[new_file_name] = os.stat( new_file_name).st_mtime self.file_watch_list.pop(file, None) else: if os.path.exists(file): self.file_watch_list[file] = os.stat( file).st_mtime self.trade_handler.updated_trade(t) if file not in updated_by_s3: update_cloud_files = True if update_cloud_files and self.enable_cloud: self.s3pers.sync(True, True) except Exception as e: self.logError(traceback.format_exc()) finally: self.start_timer() def on_trade_updated_by_handler(self, trade: Trade, needs_cloud_sync=True): with self.lock: file = self.get_file_path(self.trades_path, trade) self.config_loader.persist_updated_trade( trade, self.config_loader.json_saver(file)) self.file_watch_list[file] = os.stat(file).st_mtime self.logInfo( 'File "{}" updated by trade handler. Its mod time: {}'.format( file, self.file_watch_list[file])) self.logInfo(trade.describe()) if trade.is_completed() or trade.is_removed(): self.move_completed_trade(trade) if self.enable_cloud and needs_cloud_sync: self.s3pers.sync(True, True) def move_completed_trade(self, trade): shutil.move( self.get_file_path(self.trades_path, trade), self.get_file_path(self.completed_trades_path, trade, datetime.now().strftime('%Y-%m-%d_%H-%M-'))) def get_file_path(self, path, trade, time=''): return os.path.join( path, '{time}{fn}'.format(fn=Utils.get_file_name(trade.symbol, trade.id), time=time))
def get(self, id): return Response(response=ConfigLoader.get_json_str(self.th.get_strategy_by_id(id).trade), status=200, mimetype="application/json")