def test_validate_backtest_base_balance():
    mock_backtest = {"base_balance": 1000}
    backtest_mirror = validate_backtest(mock_backtest)
    assert backtest_mirror["base_balance"] is None

    mock_backtest = {"base_balance": "1000"}
    backtest_mirror = validate_backtest(mock_backtest)
    assert backtest_mirror["base_balance"] is None

    mock_backtest = {"base_balance": "1000.0"}
    backtest_mirror = validate_backtest(mock_backtest)
    assert backtest_mirror["base_balance"] is None

    mock_backtest = {"base_balance": 1000.0}
    backtest_mirror = validate_backtest(mock_backtest)
    assert backtest_mirror["base_balance"] is None
def test_validate_backtest_empty_1():
    mock_backtest = {}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["datapoints"]["error"] is True
    assert backtest_mirror["exit"]["error"] is True
    assert backtest_mirror["enter"]["error"] is True
def test_validate_basic_invalid():
    mock_backtest = {
        "base_balance": "c1000",
        "chart_period": "1Min22",
    }

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["base_balance"].get("error") is True
    assert backtest_mirror["chart_period"].get("error") is True
Esempio n. 4
0
def run_backtest(backtest: dict,
                 ohlcv_path: str = "",
                 df: pd.DataFrame = None,
                 summary=True):
    """
    Parameters
        backtest: dict, required, object containing the logic to test and other details
        ohlcv_path: string or list, required, where to find the csv file of the ohlcv data
        df: pandas dataframe indexed by date
    Returns
        dict
            summary dict, summary of the performace of backtest
            df dataframe, object used in the backtest
            trade_log, dataframe of all the rows where transactions happened
    """

    try:
        perf_start_time = datetime.datetime.utcnow()
        new_backtest = prepare_new_backtest(backtest)
        if ohlcv_path:
            df = build_data_frame(backtest, ohlcv_path)

        df = apply_backtest_to_df(df, new_backtest)

        if summary:
            summary, trade_log = build_summary(df, perf_start_time,
                                               new_backtest)
        else:
            perf_stop_time = datetime.datetime.utcnow()
            summary = {
                "test_duration":
                (perf_stop_time - perf_start_time).total_seconds()
            }
            trade_log = None

        return {
            "summary": summary,
            "df": df,
            "trade_df": trade_log,
            "backtest": new_backtest,
        }
    except Exception as e:
        return {
            "summary": None,
            "df": None,
            "trade_df": None,
            "backtest": None,
            "error": e,
            "backtest_validation": validate_backtest(backtest),
        }
def test_validate_data_points_invalid_name():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "ema",
            "name": ""
        },
    ]

    mock_backtest = {"datapoints": mock_datapoints}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["datapoints"].get("error") is True
def test_validate_data_points_invalid():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "fake_news_transformer",
            "name": "sma_short"
        },
    ]

    mock_backtest = {"datapoints": mock_datapoints}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["datapoints"].get("error") is True
def test_validate_data_points_valid():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "sma",
            "name": "sma_short"
        },
    ]

    mock_backtest = {"datapoints": mock_datapoints}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["datapoints"] is None
def test_validate_enter_logic_valid():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "sma",
            "name": "sma_short"
        },
    ]

    mock_enter_logic = [["close", ">", "sma_short"]]

    mock_backtest = {"datapoints": mock_datapoints, "enter": mock_enter_logic}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["datapoints"] is None
def test_validate_enter_logic_invalid_1():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "sma",
            "name": "sma_short"
        },
    ]

    mock_enter_logic = [["close", ">", "sma_shortee"]]

    mock_backtest = {"datapoints": mock_datapoints, "enter": mock_enter_logic}

    backtest_mirror = validate_backtest(mock_backtest)

    assert backtest_mirror["enter"].get("error") is True
def test_validate_any_exit_logic_invalid_1():
    mock_datapoints = [
        {
            "args": [30],
            "transformer": "sma",
            "name": "wtf"
        },
    ]

    mock_exit_logic = [["close", ">", "no name here"]]

    mock_backtest = {
        "datapoints": mock_datapoints,
        "exit": [],
        "enter": [],
        "any_exit": mock_exit_logic
    }

    backtest_mirror = validate_backtest(mock_backtest)

    print(backtest_mirror)

    assert backtest_mirror["any_exit"].get("error") is True
Esempio n. 11
0
def main():
    parser = argparse.ArgumentParser(
        description="Fast Trade CLI",
        prog="ft",
    )

    sub_parsers = parser.add_subparsers()

    # build the argement parser downloading stuff
    default_archive_path = os.path.join(os.getcwd(), "archive")
    default_end_date = datetime.datetime.utcnow()
    default_start_date = default_end_date - datetime.timedelta(days=30)

    download_parser = sub_parsers.add_parser("download", help="download data")
    download_parser.add_argument("symbol", help="symbol to download", type=str)
    download_parser.add_argument(
        "--archive",
        help="path to directory to serve as the 'archive'",
        type=str,
        default=default_archive_path,
    )

    download_parser.add_argument(
        "--start",
        help=
        "first date to start downloading data from. Recently Listed coins might not have a lot of data.",
        type=str,
        default=default_start_date.strftime("%Y-%m-%d"),
    )

    download_parser.add_argument(
        "--end",
        help="Last date to download data. Defaults to today.",
        type=str,
        default=default_end_date.strftime("%Y-%m-%d"),
    )

    download_parser.add_argument(
        "--exchange",
        help="Which exchange to download data from. Defaults to binance.com",
        type=str,
        default="binance.com",
        choices=["binance.com", "binance.us"],
    )

    backtest_parser = sub_parsers.add_parser("backtest",
                                             help="backtest a strategy")
    backtest_parser.add_argument(
        "strategy",
        help="path to strategy file",
        type=str,
    )

    backtest_parser.add_argument("data",
                                 help="path to data file for kline data.")
    backtest_parser.add_argument("--mods",
                                 help="Modifiers for strategy/backtest",
                                 nargs="*")
    backtest_parser.add_argument(
        "--save",
        help="save the backtest results to a directory",
        action="store_true",
        default=False,
    )
    backtest_parser.add_argument(
        "--plot",
        help="plot the backtest results",
        action="store_true",
        default=False,
    )

    validate_backtest_parser = sub_parsers.add_parser(
        "validate", help="validate a strategy file")

    validate_backtest_parser.add_argument(
        "strategy",
        help="path to strategy file",
        type=str,
    )
    validate_backtest_parser.add_argument(
        "--mods", help="Modifiers for strategy/backtest", nargs="*")

    args = parser.parse_args()
    command = sys.argv[1]

    if command == "download":
        update_symbol_data(args.symbol, args.start, args.end, args.archive,
                           args.exchange)

    if command == "backtest":
        # match the mods to the kwargs
        strat_obj = open_strat_file(args.strategy)

        if not strat_obj:
            print("Could not open strategy file: {}".format(args.strategy))
            sys.exit(1)
        if args.mods:
            mods = {}
            i = 0
            while i < len(args.mods):
                mods[args.mods[i]] = args.mods[i + 1]
                i += 2

            strat_obj = {**strat_obj, **mods}
        backtest = run_backtest(strat_obj, data_path=args.data)

        if args.save:
            save(backtest, backtest["backtest"])

        if args.plot:
            create_plot(backtest["df"])

            plt.show()
        print(backtest)
        pprint(backtest["summary"])

    if command == "validate":
        strat_obj = open_strat_file(args.strategy)
        if args.mods:
            mods = {}
            i = 0
            while i < len(args.mods):
                mods[args.mods[i]] = args.mods[i + 1]
                i += 2

            strat_obj = {**strat_obj, **mods}

        backtest = validate_backtest(strat_obj)

        pprint(backtest)
Esempio n. 12
0
            "args": [30],
            "transformer": "sma",
            "name": "sma_shorst"
        },
        {
            "args": [90],
            "transformer": "sma",
            "name": "sma_long"
        },
    ],
    "enter": [["close", ">", "sma_long_wrong"], ["close", ">", "sma_short"]],
    "exit": [["close", "<", "sma_short"], ["close", "<", 5]],
    "trailing_stop_loss":
    0.05,
    "exit_on_end":
    False,
}

if __name__ == "__main__":
    # datafile = "./BTCUSDT.csv"
    datafile = "./BTCUSDT.csv"
    tmp_start = datetime.datetime.utcnow()
    # backtest = generate_backtest()
    # print("backtest: ",json.dumps(backtest, indent=2)
    # test = run_backtest(backtest, ohlcv_path=datafile, summary=True)
    res = validate_backtest(backtest)
    print(res)
    # print(backtest["enter"])
    # print(test["trade_df"]) .
    # print(json.dumps(test["summary"], indent=2))
Esempio n. 13
0
def main():
    if len(sys.argv) < 2:
        print(format_all_help_text())
        return

    command = sys.argv[1]

    args = parse_args(sys.argv[2:])

    if command == "backtest":
        # check for help
        if "help" in args.keys():
            print(format_command(command))
            return

        strat_obj = open_strat_file(args["backtest"])
        strat_obj = {**strat_obj, **args}

        if args.get("data", "").endswith(".csv"):
            # use a csv file
            data = args["data"]
            res = run_backtest(strat_obj, ohlcv_path=data)
        else:
            # load from the archive
            archive = args.get("archive", "./archive")
            archive_df = load_archive_to_df(strat_obj["symbol"], archive)
            archive_df = prepare_df(archive_df, strat_obj)
            res = run_backtest(strat_obj, df=archive_df)

        if res["summary"]:
            print(json.dumps((res["summary"]), indent=2))
        else:
            print("There was an error:")
            print(json.dumps((res["backtest_validation"]), indent=2))

        if args.get("save"):
            save(res, strat_obj)

        if args.get("plot"):
            create_plot(res["df"])

            plt.show()

        return

    if command == "help":
        print(format_all_help_text())
        return

    if command == "download":
        default_end = (
            datetime.datetime.utcnow() + datetime.timedelta(days=1)
        ).strftime("%Y-%m-%d")
        symbol = args.get("symbol", "BTCUSDT")
        arc_path = args.get("archive", "./archive/")
        start_date = args.get("start", "2017-01-01")
        end_date = args.get("end", default_end)
        exchange = args.get("exchange", "binance.com")
        update_symbol_data(symbol, start_date, end_date, arc_path, exchange)

        print("Done downloading ", symbol)
        return

    if command == "validate":
        print("args: ",args)
        backtest = open_strat_file(args["backtest"])
        if not backtest:
            print("backtest not found! ")
            return
        print("backtest: ",backtest)
        backtest = {**backtest, **args}

        res = validate_backtest(backtest)

        print(json.dumps(res, indent=2))
        return
    print("Command not found")
    print(format_all_help_text())
Esempio n. 14
0
    0,
    "datapoints": [{
        "args": [14],
        "name": "er",
        "transformer": "er"
    }, {
        "args": [13],
        "name": "zlema",
        "transformer": "zlema"
    }],
    "enter": [["zlema", ">", "close", 1]],
    "exit": [["er", "<", 0, 1]],
    "exit_on_end":
    False,
    "start":
    "2021-01-01 22:30:00",
    "stop":
    "2021-03-11 23:30:59",
    "trailing_stop_loss":
    0
}

if __name__ == "__main__":
    # datafile = "./BTCUSDT.csv"
    datafile = "./archive/BTCUSDT_2021.csv"
    # test = run_backtest(backtest, ohlcv_path=datafile, summary=True)
    # print(test["summary"])
    errors = validate_backtest(backtest)

    print(errors)