async def main(): parser = argparse.ArgumentParser(prog='Backtest', description='Backtest given passivbot config.') parser.add_argument('live_config_path', type=str, help='path to live config to test') parser = add_argparse_args(parser) parser.add_argument( "-lw", "--long_wallet_exposure_limit", "--long-wallet-exposure-limit", type=float, required=False, dest="long_wallet_exposure_limit", default=None, help="specify long wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sw", "--short_wallet_exposure_limit", "--short-wallet-exposure-limit", type=float, required=False, dest="short_wallet_exposure_limit", default=None, help="specify short wallet exposure limit, overriding value from live config", ) args = parser.parse_args() config = await prepare_backtest_config(args) live_config = load_live_config(args.live_config_path) config.update(live_config) if args.long_wallet_exposure_limit is not None: print( f"overriding long wallet exposure limit ({config['long']['pbr_limit']}) " f"with new value: {args.long_wallet_exposure_limit}" ) config["long"]["pbr_limit"] = args.long_wallet_exposure_limit if args.short_wallet_exposure_limit is not None: print( f"overriding short wallet exposure limit ({config['shrt']['pbr_limit']}) " f"with new value: {args.short_wallet_exposure_limit}" ) config["shrt"]["pbr_limit"] = args.short_wallet_exposure_limit if 'spot' in config['market_type']: live_config = spotify_config(live_config) downloader = Downloader(config) print() for k in (keys := ['exchange', 'spot', 'symbol', 'market_type', 'config_type', 'starting_balance', 'start_date', 'end_date', 'latency_simulation_ms']): if k in config: print(f"{k: <{max(map(len, keys)) + 2}} {config[k]}")
async def main() -> None: parser = argparse.ArgumentParser(prog='passivbot', description='run passivbot') parser.add_argument('user', type=str, help='user/account_name defined in api-keys.json') parser.add_argument('symbol', type=str, help='symbol to trade') parser.add_argument('live_config_path', type=str, help='live config to use') parser.add_argument( '-m', '--market_type', type=str, required=False, dest='market_type', default=None, help= 'specify whether spot or futures (default), overriding value from backtest config' ) parser.add_argument('-gs', '--graceful_stop', action='store_true', help='if true, disable long and short') parser.add_argument( "-lw", "--long_wallet_exposure_limit", "--long-wallet-exposure-limit", type=float, required=False, dest="long_wallet_exposure_limit", default=None, help= "specify long wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sw", "--short_wallet_exposure_limit", "--short-wallet-exposure-limit", type=float, required=False, dest="short_wallet_exposure_limit", default=None, help= "specify short wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sm", "--short_mode", "--short-mode", type=str, required=False, dest="short_mode", default=None, help= "specify one of following short modes: [n (normal), m (manual), gs (graceful_stop), p (panic), t (tp_only)]" ) parser.add_argument( "-lm", "--long_mode", "--long-mode", type=str, required=False, dest="long_mode", default=None, help= "specify one of following long modes: [n (normal), m (manual), gs (graceful_stop), p (panic), t (tp_only)]" ) parser.add_argument('-ab', '--assigned_balance', type=float, required=False, dest='assigned_balance', default=None, help='add assigned_balance to live config') args = parser.parse_args() try: accounts = json.load(open('api-keys.json')) except Exception as e: print(e, 'failed to load api-keys.json file') return try: account = accounts[args.user] except Exception as e: print('unrecognized account name', args.user, e) return try: config = load_live_config(args.live_config_path) except Exception as e: print(e, 'failed to load config', args.live_config_path) return config['user'] = args.user config['exchange'] = account['exchange'] config['symbol'] = args.symbol config['live_config_path'] = args.live_config_path config[ 'market_type'] = args.market_type if args.market_type is not None else 'futures' if args.assigned_balance is not None: print(f'\nassigned balance set to {args.assigned_balance}\n') config['assigned_balance'] = args.assigned_balance if args.long_mode is not None: if args.long_mode in ['gs', 'graceful_stop', 'graceful-stop']: print( '\n\nlong graceful stop enabled; will not make new entries once existing positions are closed\n' ) config['long']['enabled'] = config['do_long'] = False elif args.long_mode in ['m', 'manual']: print( '\n\nlong manual mode enabled; will neither cancel nor create long orders' ) config['long_mode'] = 'manual' elif args.long_mode in ['n', 'normal']: print('\n\nlong normal mode') config['long']['enabled'] = config['do_long'] = True elif args.long_mode in ['p', 'panic']: print('\nlong panic mode enabled') config['long_mode'] = 'panic' config['long']['enabled'] = config['do_long'] = False elif args.long_mode.lower() in ['t', 'tp_only', 'tp-only']: print('\nlong tp only mode enabled') config['long_mode'] = 'tp_only' if args.short_mode is not None: if args.short_mode in ['gs', 'graceful_stop', 'graceful-stop']: print( '\n\nshrt graceful stop enabled; will not make new entries once existing positions are closed\n' ) config['shrt']['enabled'] = config['do_shrt'] = False elif args.short_mode in ['m', 'manual']: print( '\n\nshrt manual mode enabled; will neither cancel nor create shrt orders' ) config['shrt_mode'] = 'manual' elif args.short_mode in ['n', 'normal']: print('\n\nshrt normal mode') config['shrt']['enabled'] = config['do_shrt'] = True elif args.short_mode in ['p', 'panic']: print('\nshort panic mode enabled') config['shrt_mode'] = 'panic' config['shrt']['enabled'] = config['do_shrt'] = False elif args.short_mode.lower() in ['t', 'tp_only', 'tp-only']: print('\nshort tp only mode enabled') config['shrt_mode'] = 'tp_only' if args.graceful_stop: print( '\n\ngraceful stop enabled for both long and short; will not make new entries once existing positions are closed\n' ) config['long']['enabled'] = config['do_long'] = False config['shrt']['enabled'] = config['do_shrt'] = False if args.long_wallet_exposure_limit is not None: print( f"overriding long wallet exposure limit ({config['long']['pbr_limit']}) " f"with new value: {args.long_wallet_exposure_limit}") config["long"]["pbr_limit"] = args.long_wallet_exposure_limit if args.short_wallet_exposure_limit is not None: print( f"overriding short wallet exposure limit ({config['shrt']['pbr_limit']}) " f"with new value: {args.short_wallet_exposure_limit}") config["shrt"]["pbr_limit"] = args.short_wallet_exposure_limit if 'spot' in config['market_type']: config = spotify_config(config) if account['exchange'] == 'binance': if 'spot' in config['market_type']: from procedures import create_binance_bot_spot bot = await create_binance_bot_spot(config) else: from procedures import create_binance_bot bot = await create_binance_bot(config) elif account['exchange'] == 'bybit': from procedures import create_bybit_bot bot = await create_bybit_bot(config) else: raise Exception('unknown exchange', account['exchange']) print('using config') pprint.pprint(denumpyize(config)) signal.signal(signal.SIGINT, bot.stop) signal.signal(signal.SIGTERM, bot.stop) await start_bot(bot) await bot.session.close()
async def main(): logging.basicConfig(format="", level=os.environ.get("LOGLEVEL", "INFO")) parser = argparse.ArgumentParser( prog="Optimize multi symbol", description="Optimize passivbot config multi symbol") parser.add_argument( "-o", "--optimize_config", type=str, required=False, dest="optimize_config_path", default="configs/optimize/harmony_search.hjson", help="optimize config hjson file", ) parser.add_argument( "-t", "--start", type=str, required=False, dest="starting_configs", default=None, help= "start with given live configs. single json file or dir with multiple json files", ) parser.add_argument("-i", "--iters", type=int, required=False, dest="iters", default=None, help="n optimize iters") parser.add_argument("-c", "--n_cpus", type=int, required=False, dest="n_cpus", default=None, help="n cpus") parser.add_argument( "-le", "--long", type=str, required=False, dest="long_enabled", default=None, help="long enabled: [y/n]", ) parser.add_argument( "-se", "--short", type=str, required=False, dest="short_enabled", default=None, help="short enabled: [y/n]", ) parser.add_argument( "-pm", "--passivbot_mode", "--passivbot-mode", type=str, required=False, dest="passivbot_mode", default=None, help="passivbot mode options: [s/static_grid, r/recursive_grid]", ) parser.add_argument( "-sf", "--score_formula", "--score-formula", type=str, required=False, dest="score_formula", default=None, help= "passivbot score formula options: [adg_PAD_mean, adg_PAD_std, adg_DGstd_ratio, adg_mean, adg_min, adg_PAD_std_min]", ) parser.add_argument( "-oh", "--ohlcv", help="use 1m ohlcv instead of 1s ticks", action="store_true", ) parser = add_argparse_args(parser) args = parser.parse_args() args.symbol = "BTCUSDT" # dummy symbol config = await prepare_optimize_config(args) if args.score_formula is not None: if args.score_formula not in [ "adg_PAD_mean", "adg_PAD_std", "adg_DGstd_ratio", "adg_mean", "adg_min", "adg_PAD_std_min", ]: logging.error(f"unknown score formula {args.score_formula}") logging.error(f"using score formula {config['score_formula']}") else: config["score_formula"] = args.score_formula if args.passivbot_mode is not None: if args.passivbot_mode in ["s", "static_grid", "static"]: config["passivbot_mode"] = "static_grid" elif args.passivbot_mode in ["r", "recursive_grid", "recursive"]: config["passivbot_mode"] = "recursive_grid" else: raise Exception(f"unknown passivbot mode {args.passivbot_mode}") passivbot_mode = config["passivbot_mode"] assert passivbot_mode in [ "recursive_grid", "static_grid", ], f"unknown passivbot mode {passivbot_mode}" config.update(get_template_live_config(passivbot_mode)) config["exchange"], _, _ = load_exchange_key_secret(config["user"]) args = parser.parse_args() if args.long_enabled is None: config["long"]["enabled"] = config["do_long"] else: if "y" in args.long_enabled.lower(): config["long"]["enabled"] = config["do_long"] = True elif "n" in args.long_enabled.lower(): config["long"]["enabled"] = config["do_long"] = False else: raise Exception("please specify y/n with kwarg -le/--long") if args.short_enabled is None: config["short"]["enabled"] = config["do_short"] else: if "y" in args.short_enabled.lower(): config["short"]["enabled"] = config["do_short"] = True elif "n" in args.short_enabled.lower(): config["short"]["enabled"] = config["do_short"] = False else: raise Exception("please specify y/n with kwarg -le/--short") if args.symbol is not None: config["symbols"] = args.symbol.split(",") if args.n_cpus is not None: config["n_cpus"] = args.n_cpus config["ohlcv"] = args.ohlcv print() lines = [(k, getattr(args, k)) for k in args.__dict__ if args.__dict__[k] is not None] for line in lines: logging.info( f"{line[0]: <{max([len(x[0]) for x in lines]) + 2}} {line[1]}") print() # download ticks .npy file if missing if config["ohlcv"]: cache_fname = f"{config['start_date']}_{config['end_date']}_ohlcv_cache.npy" else: cache_fname = f"{config['start_date']}_{config['end_date']}_ticks_cache.npy" exchange_name = config["exchange"] + ("_spot" if config["market_type"] == "spot" else "") config["symbols"] = sorted(config["symbols"]) for symbol in config["symbols"]: cache_dirpath = f"backtests/{exchange_name}/{symbol}/caches/" if not os.path.exists(cache_dirpath + cache_fname) or not os.path.exists( cache_dirpath + "market_specific_settings.json"): logging.info(f"fetching data {symbol}") args.symbol = symbol if config["ohlcv"]: data = load_hlc_cache( symbol, config["start_date"], config["end_date"], base_dir=config["base_dir"], spot=config["spot"], ) else: tmp_cfg = await prepare_backtest_config(args) downloader = Downloader({**config, **tmp_cfg}) await downloader.get_sampled_ticks() # prepare starting configs cfgs = [] if args.starting_configs is not None: logging.info("preparing starting configs...") if os.path.isdir(args.starting_configs): for fname in os.listdir(args.starting_configs): try: cfg = load_live_config( os.path.join(args.starting_configs, fname)) assert determine_passivbot_mode( cfg) == passivbot_mode, "wrong passivbot mode" cfgs.append(cfg) except Exception as e: logging.error(f"error loading config {fname}: {e}") elif os.path.exists(args.starting_configs): hm_load_failed = True if "hm_" in args.starting_configs: try: hm = json.load(open(args.starting_configs)) for k in hm: cfg = { "long": hm[k]["long"]["config"], "short": hm[k]["short"]["config"] } assert (determine_passivbot_mode(cfg) == passivbot_mode ), "wrong passivbot mode in harmony memory" cfgs.append(cfg) logging.info( f"loaded harmony memory {args.starting_configs}") hm_load_failed = False except Exception as e: logging.error( f"error loading harmony memory {args.starting_configs}: {e}" ) if hm_load_failed: try: cfg = load_live_config(args.starting_configs) assert determine_passivbot_mode( cfg) == passivbot_mode, "wrong passivbot mode" cfgs.append(cfg) except Exception as e: logging.error( f"error loading config {args.starting_configs}: {e}") config["starting_configs"] = cfgs harmony_search = HarmonySearch(config) harmony_search.run()
async def main(): parser = argparse.ArgumentParser( prog="Backtest", description="Backtest given passivbot config.") parser.add_argument("live_config_path", type=str, help="path to live config to test") parser = add_argparse_args(parser) parser.add_argument( "-lw", "--long_wallet_exposure_limit", "--long-wallet-exposure-limit", type=float, required=False, dest="long_wallet_exposure_limit", default=None, help= "specify long wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sw", "--short_wallet_exposure_limit", "--short-wallet-exposure-limit", type=float, required=False, dest="short_wallet_exposure_limit", default=None, help= "specify short wallet exposure limit, overriding value from live config", ) parser.add_argument( "-le", "--long_enabled", "--long-enabled", type=str, required=False, dest="long_enabled", default=None, help="specify long enabled [y/n], overriding value from live config", ) parser.add_argument( "-se", "--short_enabled", "--short-enabled", type=str, required=False, dest="short_enabled", default=None, help="specify short enabled [y/n], overriding value from live config", ) parser.add_argument( "-np", "--n_parts", "--n-parts", type=int, required=False, dest="n_parts", default=None, help="set n backtest slices to plot", ) parser.add_argument( "-oh", "--ohlcv", help="use 1m ohlcv instead of 1s ticks", action="store_true", ) args = parser.parse_args() if args.symbol is None: tmp_cfg = load_hjson_config(args.backtest_config_path) symbols = (tmp_cfg["symbol"] if type(tmp_cfg["symbol"]) == list else tmp_cfg["symbol"].split(",")) else: symbols = args.symbol.split(",") for symbol in symbols: args = parser.parse_args() args.symbol = symbol config = await prepare_backtest_config(args) config["n_parts"] = args.n_parts live_config = load_live_config(args.live_config_path) config.update(live_config) if args.long_wallet_exposure_limit is not None: print( f"overriding long wallet exposure limit ({config['long']['wallet_exposure_limit']}) " f"with new value: {args.long_wallet_exposure_limit}") config["long"][ "wallet_exposure_limit"] = args.long_wallet_exposure_limit if args.short_wallet_exposure_limit is not None: print( f"overriding short wallet exposure limit ({config['short']['wallet_exposure_limit']}) " f"with new value: {args.short_wallet_exposure_limit}") config["short"][ "wallet_exposure_limit"] = args.short_wallet_exposure_limit if args.long_enabled is not None: config["long"]["enabled"] = "y" in args.long_enabled.lower() if args.short_enabled is not None: config["short"]["enabled"] = "y" in args.short_enabled.lower() if "spot" in config["market_type"]: live_config = spotify_config(live_config) config["ohlcv"] = args.ohlcv print() for k in (keys := [ "exchange", "spot", "symbol", "market_type", "passivbot_mode", "config_type", "starting_balance", "start_date", "end_date", "latency_simulation_ms", "base_dir", ]): if k in config: print(f"{k: <{max(map(len, keys)) + 2}} {config[k]}") print() if config["ohlcv"]: data = load_hlc_cache( symbol, config["start_date"], config["end_date"], base_dir=config["base_dir"], spot=config["spot"], ) else: downloader = Downloader(config) data = await downloader.get_sampled_ticks() config["n_days"] = round_( (data[-1][0] - data[0][0]) / (1000 * 60 * 60 * 24), 0.1) pprint.pprint(denumpyize(live_config)) plot_wrap(config, data)
async def main(): parser = argparse.ArgumentParser(prog='Optimize multi symbol', description='Optimize passivbot config multi symbol') parser.add_argument('-o', '--optimize_config', type=str, required=False, dest='optimize_config_path', default='configs/optimize/multi_symbol.hjson', help='optimize config hjson file') parser.add_argument('-t', '--start', type=str, required=False, dest='starting_configs', default=None, help='start with given live configs. single json file or dir with multiple json files') parser.add_argument('-i', '--iters', type=int, required=False, dest='iters', default=None, help='n optimize iters') parser = add_argparse_args(parser) args = parser.parse_args() args.symbol = 'BTCUSDT' # dummy symbol config = await prepare_optimize_config(args) config.update(get_template_live_config()) config['exchange'], _, _ = load_exchange_key_secret(config['user']) config['long']['enabled'] = config['do_long'] config['shrt']['enabled'] = config['do_shrt'] if config['long']['enabled']: if config['shrt']['enabled']: print('optimizing both long and short') config['side'] = 'both' else: print('optimizing long') config['side'] = 'long' elif config['shrt']['enabled']: print('optimizing short') config['side'] = 'shrt' else: raise Exception('long, shrt or both must be enabled') # download ticks .npy file if missing cache_fname = f"{config['start_date']}_{config['end_date']}_ticks_cache.npy" exchange_name = config['exchange'] + ('_spot' if config['market_type'] == 'spot' else '') for symbol in sorted(config['symbols']): cache_dirpath = f"backtests/{exchange_name}/{symbol}/caches/" if not os.path.exists(cache_dirpath + cache_fname) or not os.path.exists(cache_dirpath + 'market_specific_settings.json'): print(f'fetching data {symbol}') args.symbol = symbol tmp_cfg = await prepare_backtest_config(args) downloader = Downloader({**config, **tmp_cfg}) await downloader.get_sampled_ticks() pool = Pool(processes=config['n_cpus']) func_wrap = FuncWrap(pool, config) cfgs = [] if args.starting_configs is not None: if os.path.isdir(args.starting_configs): cfgs = [] for fname in os.listdir(args.starting_configs): try: cfgs.append(load_live_config(os.path.join(args.starting_configs, fname))) except Exception as e: print('error loading config:', e) elif os.path.exists(args.starting_configs): try: cfgs = [load_live_config(args.starting_configs)] except Exception as e: print('error loading config:', e) starting_xs = [func_wrap.config_to_xs(cfg) for cfg in cfgs] n_harmonies = config['n_harmonies'] hm_considering_rate = config['hm_considering_rate'] bandwidth = config['bandwidth'] pitch_adjusting_rate = config['pitch_adjusting_rate'] iters = config['iters'] best_harmony = harmony_search(func_wrap.func, func_wrap.bounds, n_harmonies, hm_considering_rate, bandwidth, pitch_adjusting_rate, iters, starting_xs=starting_xs, post_processing_func=func_wrap.post_processing_func) best_conf = func_wrap.xs_to_config(best_harmony) print('best conf') print(best_conf) return
async def main() -> None: parser = argparse.ArgumentParser(prog="passivbot", description="run passivbot") parser.add_argument("user", type=str, help="user/account_name defined in api-keys.json") parser.add_argument("symbol", type=str, help="symbol to trade") parser.add_argument("live_config_path", type=str, help="live config to use") parser.add_argument( "-m", "--market_type", type=str, required=False, dest="market_type", default=None, help= "specify whether spot or futures (default), overriding value from backtest config", ) parser.add_argument( "-gs", "--graceful_stop", action="store_true", help="if true, disable long and short", ) parser.add_argument( "-lw", "--long_wallet_exposure_limit", "--long-wallet-exposure-limit", type=float, required=False, dest="long_wallet_exposure_limit", default=None, help= "specify long wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sw", "--short_wallet_exposure_limit", "--short-wallet-exposure-limit", type=float, required=False, dest="short_wallet_exposure_limit", default=None, help= "specify short wallet exposure limit, overriding value from live config", ) parser.add_argument( "-sm", "--short_mode", "--short-mode", type=str, required=False, dest="short_mode", default=None, help= "specify one of following short modes: [n (normal), m (manual), gs (graceful_stop), p (panic), t (tp_only)]", ) parser.add_argument( "-lm", "--long_mode", "--long-mode", type=str, required=False, dest="long_mode", default=None, help= "specify one of following long modes: [n (normal), m (manual), gs (graceful_stop), p (panic), t (tp_only)]", ) parser.add_argument( "-ab", "--assigned_balance", type=float, required=False, dest="assigned_balance", default=None, help="add assigned_balance to live config", ) args = parser.parse_args() try: accounts = json.load(open("api-keys.json")) except Exception as e: print(e, "failed to load api-keys.json file") return try: account = accounts[args.user] except Exception as e: print("unrecognized account name", args.user, e) return try: config = load_live_config(args.live_config_path) except Exception as e: print(e, "failed to load config", args.live_config_path) return config["user"] = args.user config["exchange"] = account["exchange"] config["symbol"] = args.symbol config[ "market_type"] = args.market_type if args.market_type is not None else "futures" config["passivbot_mode"] = determine_passivbot_mode(config) if args.assigned_balance is not None: print(f"\nassigned balance set to {args.assigned_balance}\n") config["assigned_balance"] = args.assigned_balance if args.long_mode is None: if not config["long"]["enabled"]: config["long_mode"] = "manual" else: if args.long_mode in ["gs", "graceful_stop", "graceful-stop"]: print( "\n\nlong graceful stop enabled; will not make new entries once existing positions are closed\n" ) config["long"]["enabled"] = config["do_long"] = False elif args.long_mode in ["m", "manual"]: print( "\n\nlong manual mode enabled; will neither cancel nor create long orders" ) config["long_mode"] = "manual" elif args.long_mode in ["n", "normal"]: print("\n\nlong normal mode") config["long"]["enabled"] = config["do_long"] = True elif args.long_mode in ["p", "panic"]: print("\nlong panic mode enabled") config["long_mode"] = "panic" config["long"]["enabled"] = config["do_long"] = False elif args.long_mode.lower() in ["t", "tp_only", "tp-only"]: print("\nlong tp only mode enabled") config["long_mode"] = "tp_only" if args.short_mode is None: if not config["short"]["enabled"]: config["short_mode"] = "manual" else: if args.short_mode in ["gs", "graceful_stop", "graceful-stop"]: print( "\n\nshort graceful stop enabled; will not make new entries once existing positions are closed\n" ) config["short"]["enabled"] = config["do_short"] = False elif args.short_mode in ["m", "manual"]: print( "\n\nshort manual mode enabled; will neither cancel nor create short orders" ) config["short_mode"] = "manual" elif args.short_mode in ["n", "normal"]: print("\n\nshort normal mode") config["short"]["enabled"] = config["do_short"] = True elif args.short_mode in ["p", "panic"]: print("\nshort panic mode enabled") config["short_mode"] = "panic" config["short"]["enabled"] = config["do_short"] = False elif args.short_mode.lower() in ["t", "tp_only", "tp-only"]: print("\nshort tp only mode enabled") config["short_mode"] = "tp_only" if args.graceful_stop: print( "\n\ngraceful stop enabled for both long and short; will not make new entries once existing positions are closed\n" ) config["long"]["enabled"] = config["do_long"] = False config["short"]["enabled"] = config["do_short"] = False config["long_mode"] = None config["short_mode"] = None if args.long_wallet_exposure_limit is not None: print( f"overriding long wallet exposure limit ({config['long']['wallet_exposure_limit']}) " f"with new value: {args.long_wallet_exposure_limit}") config["long"][ "wallet_exposure_limit"] = args.long_wallet_exposure_limit if args.short_wallet_exposure_limit is not None: print( f"overriding short wallet exposure limit ({config['short']['wallet_exposure_limit']}) " f"with new value: {args.short_wallet_exposure_limit}") config["short"][ "wallet_exposure_limit"] = args.short_wallet_exposure_limit if "spot" in config["market_type"]: config = spotify_config(config) if account["exchange"] == "binance": if "spot" in config["market_type"]: from procedures import create_binance_bot_spot bot = await create_binance_bot_spot(config) else: from procedures import create_binance_bot bot = await create_binance_bot(config) elif account["exchange"] == "binance_us": from procedures import create_binance_bot_spot bot = await create_binance_bot_spot(config) elif account["exchange"] == "bybit": from procedures import create_bybit_bot bot = await create_bybit_bot(config) else: raise Exception("unknown exchange", account["exchange"]) print("using config") pprint.pprint(denumpyize(config)) signal.signal(signal.SIGINT, bot.stop) signal.signal(signal.SIGTERM, bot.stop) await start_bot(bot) await bot.session.close()
]): if k in config: print(f"{k: <{max(map(len, keys)) + 2}} {config[k]}") print() data = await downloader.get_sampled_ticks() config['n_days'] = (data[-1][0] - data[0][0]) / (1000 * 60 * 60 * 24) config['optimize_dirpath'] = os.path.join( config['optimize_dirpath'], ts_to_date(time())[:19].replace(':', ''), '') start_candidate = None if config['starting_configs'] is not None: try: if os.path.isdir(config['starting_configs']): start_candidate = [ load_live_config(f) for f in glob.glob( os.path.join(config['starting_configs'], '*.json')) ] print('Starting with all configurations in directory.') else: start_candidate = load_live_config(config['starting_configs']) print('Starting with specified configuration.') except Exception as e: print('Could not find specified configuration.', e) analysis = backtest_tune(data, config, start_candidate) if analysis: save_results(analysis, config) config.update(clean_result_config(analysis.best_config)) plot_wrap(pack_config(config), data)