コード例 #1
0
ファイル: backtest.py プロジェクト: pbosch/passivbot
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]}")
コード例 #2
0
ファイル: passivbot.py プロジェクト: migueltg/passivbot
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()
コード例 #3
0
ファイル: harmony_search.py プロジェクト: enarjord/passivbot
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()
コード例 #4
0
ファイル: backtest.py プロジェクト: enarjord/passivbot
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)
コード例 #5
0
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
コード例 #6
0
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()
コード例 #7
0
    ]):
        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)