diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc0c8a5d7..e45f85481 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,17 +73,17 @@ jobs: python build_helpers/freqtrade_client_version_align.py - name: Tests - if: (!(runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-22.04')) + if: (!(runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-24.04')) run: | pytest --random-order - name: Tests with Coveralls - if: (runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-22.04') + if: (runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-24.04') run: | pytest --random-order --cov=freqtrade --cov=freqtrade_client --cov-config=.coveragerc - name: Coveralls - if: (runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-22.04') + if: (runner.os == 'Linux' && matrix.python-version == '3.12' && matrix.os == 'ubuntu-24.04') env: # Coveralls token. Not used as secret due to github not providing secrets to forked repositories COVERALLS_REPO_TOKEN: 6D1m0xupS3FgutfuGao8keFf9Hc0FpIXu @@ -139,6 +139,7 @@ jobs: ruff format --check - name: Mypy + if: matrix.os == 'ubuntu-24.04' run: | mypy freqtrade scripts tests @@ -264,6 +265,7 @@ jobs: ruff format --check - name: Mypy + if: matrix.os == 'macos-15' run: | mypy freqtrade scripts diff --git a/docs/backtesting.md b/docs/backtesting.md index 981f889a2..4d91b3ca6 100644 --- a/docs/backtesting.md +++ b/docs/backtesting.md @@ -435,6 +435,20 @@ To save time, by default backtest will reuse a cached result from within the las To further analyze your backtest results, freqtrade will export the trades to file by default. You can then load the trades to perform further analysis as shown in the [data analysis](strategy_analysis_example.md#load-backtest-results-to-pandas-dataframe) backtesting section. +### Backtest output file + +The output file freqtrade produces is a zip file containing the following files: + +- The backtest report in json format +- the market change data in feather format +- a copy of the strategy file +- a copy of the strategy parameters (if a parameter file was used) +- a sanitized copy of the config file + +This will ensure results are reproducible - under the assumption that the same data is available. + +Only the strategy file and the config file are included in the zip file, eventual dependencies are not included. + ## Assumptions made by backtesting Since backtesting lacks some detailed information about what happens within a candle, it needs to take a few assumptions: diff --git a/freqtrade/__init__.py b/freqtrade/__init__.py index 8ca2a3e67..8644f9eab 100644 --- a/freqtrade/__init__.py +++ b/freqtrade/__init__.py @@ -1,6 +1,6 @@ """Freqtrade bot""" -__version__ = "2025.3-dev" +__version__ = "2025.4-dev" if "dev" in __version__: from pathlib import Path diff --git a/freqtrade/exchange/binance_leverage_tiers.json b/freqtrade/exchange/binance_leverage_tiers.json index f71f2a002..4eb970b2c 100644 --- a/freqtrade/exchange/binance_leverage_tiers.json +++ b/freqtrade/exchange/binance_leverage_tiers.json @@ -8279,10 +8279,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.015, - "maxLeverage": 50.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "50", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.015", @@ -8296,10 +8296,10 @@ "minNotional": 5000.0, "maxNotional": 20000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "maxLeverage": 15.0, "info": { "bracket": "2", - "initialLeverage": "25", + "initialLeverage": "15", "notionalCap": "20000", "notionalFloor": "5000", "maintMarginRatio": "0.02", @@ -8313,10 +8313,10 @@ "minNotional": 20000.0, "maxNotional": 30000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, + "maxLeverage": 10.0, "info": { "bracket": "3", - "initialLeverage": "20", + "initialLeverage": "10", "notionalCap": "30000", "notionalFloor": "20000", "maintMarginRatio": "0.025", @@ -8330,10 +8330,10 @@ "minNotional": 30000.0, "maxNotional": 300000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 10.0, + "maxLeverage": 8.0, "info": { "bracket": "4", - "initialLeverage": "10", + "initialLeverage": "8", "notionalCap": "300000", "notionalFloor": "30000", "maintMarginRatio": "0.05", @@ -10133,6 +10133,127 @@ } } ], + "BANANAS31/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "BANANAS31/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "BAND/USDT:USDT": [ { "tier": 1.0, @@ -11477,6 +11598,127 @@ } } ], + "BID/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "BID/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "BIGTIME/USDT:USDT": [ { "tier": 1.0, @@ -13116,6 +13358,127 @@ } } ], + "BR/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "BR/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "BRETT/USDT:USDT": [ { "tier": 1.0, @@ -13271,6 +13634,248 @@ } } ], + "BROCCOLI714/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "BROCCOLI714/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], + "BROCCOLIF3B/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "BROCCOLIF3B/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "BSV/USDT:USDT": [ { "tier": 1.0, @@ -31199,6 +31804,127 @@ } } ], + "JELLYJELLY/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 300000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "300000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 300000.0, + "maxNotional": 400000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "400000", + "notionalFloor": "300000", + "maintMarginRatio": "0.125", + "cum": "18150.0" + } + }, + { + "tier": 6.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 400000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "500000", + "notionalFloor": "400000", + "maintMarginRatio": "0.25", + "cum": "68150.0" + } + }, + { + "tier": 7.0, + "symbol": "JELLYJELLY/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 600000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "600000", + "notionalFloor": "500000", + "maintMarginRatio": "0.5", + "cum": "193150.0" + } + } + ], "JOE/USDT:USDT": [ { "tier": 1.0, @@ -36739,14 +37465,14 @@ "currency": "USDT", "minNotional": 0.0, "maxNotional": 5000.0, - "maintenanceMarginRate": 0.015, - "maxLeverage": 10.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "10", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", - "maintMarginRatio": "0.015", + "maintMarginRatio": "0.02", "cum": "0.0" } }, @@ -36757,14 +37483,14 @@ "minNotional": 5000.0, "maxNotional": 25000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 8.0, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "8", + "initialLeverage": "20", "notionalCap": "25000", "notionalFloor": "5000", "maintMarginRatio": "0.025", - "cum": "50.0" + "cum": "25.0" } }, { @@ -36772,84 +37498,84 @@ "symbol": "MAVIA/USDT:USDT", "currency": "USDT", "minNotional": 25000.0, - "maxNotional": 100000.0, + "maxNotional": 200000.0, "maintenanceMarginRate": 0.05, - "maxLeverage": 6.0, + "maxLeverage": 10.0, "info": { "bracket": "3", - "initialLeverage": "6", - "notionalCap": "100000", + "initialLeverage": "10", + "notionalCap": "200000", "notionalFloor": "25000", "maintMarginRatio": "0.05", - "cum": "675.0" + "cum": "650.0" } }, { "tier": 4.0, "symbol": "MAVIA/USDT:USDT", "currency": "USDT", - "minNotional": 100000.0, - "maxNotional": 200000.0, + "minNotional": 200000.0, + "maxNotional": 500000.0, "maintenanceMarginRate": 0.1, "maxLeverage": 5.0, "info": { "bracket": "4", "initialLeverage": "5", - "notionalCap": "200000", - "notionalFloor": "100000", + "notionalCap": "500000", + "notionalFloor": "200000", "maintMarginRatio": "0.1", - "cum": "5675.0" + "cum": "10650.0" } }, { "tier": 5.0, "symbol": "MAVIA/USDT:USDT", "currency": "USDT", - "minNotional": 200000.0, - "maxNotional": 500000.0, + "minNotional": 500000.0, + "maxNotional": 750000.0, "maintenanceMarginRate": 0.125, "maxLeverage": 4.0, "info": { "bracket": "5", "initialLeverage": "4", - "notionalCap": "500000", - "notionalFloor": "200000", + "notionalCap": "750000", + "notionalFloor": "500000", "maintMarginRatio": "0.125", - "cum": "10675.0" + "cum": "23150.0" } }, { "tier": 6.0, "symbol": "MAVIA/USDT:USDT", "currency": "USDT", - "minNotional": 500000.0, - "maxNotional": 1000000.0, + "minNotional": 750000.0, + "maxNotional": 1500000.0, "maintenanceMarginRate": 0.25, "maxLeverage": 2.0, "info": { "bracket": "6", "initialLeverage": "2", - "notionalCap": "1000000", - "notionalFloor": "500000", + "notionalCap": "1500000", + "notionalFloor": "750000", "maintMarginRatio": "0.25", - "cum": "73175.0" + "cum": "116900.0" } }, { "tier": 7.0, "symbol": "MAVIA/USDT:USDT", "currency": "USDT", - "minNotional": 1000000.0, - "maxNotional": 2000000.0, + "minNotional": 1500000.0, + "maxNotional": 3000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "7", "initialLeverage": "1", - "notionalCap": "2000000", - "notionalFloor": "1000000", + "notionalCap": "3000000", + "notionalFloor": "1500000", "maintMarginRatio": "0.5", - "cum": "323175.0" + "cum": "491900.0" } } ], @@ -40284,6 +41010,161 @@ } } ], + "NIL/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.015, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "10000", + "notionalFloor": "5000", + "maintMarginRatio": "0.015", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 30000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "30000", + "notionalFloor": "10000", + "maintMarginRatio": "0.02", + "cum": "75.0" + } + }, + { + "tier": 4.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 30000.0, + "maxNotional": 60000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "4", + "initialLeverage": "20", + "notionalCap": "60000", + "notionalFloor": "30000", + "maintMarginRatio": "0.025", + "cum": "225.0" + } + }, + { + "tier": 5.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 60000.0, + "maxNotional": 300000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "5", + "initialLeverage": "10", + "notionalCap": "300000", + "notionalFloor": "60000", + "maintMarginRatio": "0.05", + "cum": "1725.0" + } + }, + { + "tier": 6.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 300000.0, + "maxNotional": 600000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "6", + "initialLeverage": "5", + "notionalCap": "600000", + "notionalFloor": "300000", + "maintMarginRatio": "0.1", + "cum": "16725.0" + } + }, + { + "tier": 7.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 600000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "7", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "600000", + "maintMarginRatio": "0.125", + "cum": "31725.0" + } + }, + { + "tier": 8.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "125475.0" + } + }, + { + "tier": 9.0, + "symbol": "NIL/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "500475.0" + } + } + ], "NKN/USDT:USDT": [ { "tier": 1.0, @@ -42415,10 +43296,10 @@ "minNotional": 0.0, "maxNotional": 5000.0, "maintenanceMarginRate": 0.01, - "maxLeverage": 75.0, + "maxLeverage": 25.0, "info": { "bracket": "1", - "initialLeverage": "75", + "initialLeverage": "25", "notionalCap": "5000", "notionalFloor": "0", "maintMarginRatio": "0.01", @@ -42432,10 +43313,10 @@ "minNotional": 5000.0, "maxNotional": 10000.0, "maintenanceMarginRate": 0.015, - "maxLeverage": 50.0, + "maxLeverage": 20.0, "info": { "bracket": "2", - "initialLeverage": "50", + "initialLeverage": "20", "notionalCap": "10000", "notionalFloor": "5000", "maintMarginRatio": "0.015", @@ -42449,10 +43330,10 @@ "minNotional": 10000.0, "maxNotional": 30000.0, "maintenanceMarginRate": 0.02, - "maxLeverage": 25.0, + "maxLeverage": 18.0, "info": { "bracket": "3", - "initialLeverage": "25", + "initialLeverage": "18", "notionalCap": "30000", "notionalFloor": "10000", "maintMarginRatio": "0.02", @@ -42466,10 +43347,10 @@ "minNotional": 30000.0, "maxNotional": 60000.0, "maintenanceMarginRate": 0.025, - "maxLeverage": 20.0, + "maxLeverage": 15.0, "info": { "bracket": "4", - "initialLeverage": "20", + "initialLeverage": "15", "notionalCap": "60000", "notionalFloor": "30000", "maintMarginRatio": "0.025", @@ -42549,13 +43430,13 @@ "symbol": "ORCA/USDT:USDT", "currency": "USDT", "minNotional": 1500000.0, - "maxNotional": 3000000.0, + "maxNotional": 2000000.0, "maintenanceMarginRate": 0.5, "maxLeverage": 1.0, "info": { "bracket": "9", "initialLeverage": "1", - "notionalCap": "3000000", + "notionalCap": "2000000", "notionalFloor": "1500000", "maintMarginRatio": "0.5", "cum": "500475.0" @@ -43027,6 +43908,161 @@ } } ], + "PARTI/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.01, + "maxLeverage": 75.0, + "info": { + "bracket": "1", + "initialLeverage": "75", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.01", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 10000.0, + "maintenanceMarginRate": 0.015, + "maxLeverage": 50.0, + "info": { + "bracket": "2", + "initialLeverage": "50", + "notionalCap": "10000", + "notionalFloor": "5000", + "maintMarginRatio": "0.015", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 10000.0, + "maxNotional": 30000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "3", + "initialLeverage": "25", + "notionalCap": "30000", + "notionalFloor": "10000", + "maintMarginRatio": "0.02", + "cum": "75.0" + } + }, + { + "tier": 4.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 30000.0, + "maxNotional": 60000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "4", + "initialLeverage": "20", + "notionalCap": "60000", + "notionalFloor": "30000", + "maintMarginRatio": "0.025", + "cum": "225.0" + } + }, + { + "tier": 5.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 60000.0, + "maxNotional": 300000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "5", + "initialLeverage": "10", + "notionalCap": "300000", + "notionalFloor": "60000", + "maintMarginRatio": "0.05", + "cum": "1725.0" + } + }, + { + "tier": 6.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 300000.0, + "maxNotional": 600000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "6", + "initialLeverage": "5", + "notionalCap": "600000", + "notionalFloor": "300000", + "maintMarginRatio": "0.1", + "cum": "16725.0" + } + }, + { + "tier": 7.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 600000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "7", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "600000", + "maintMarginRatio": "0.125", + "cum": "31725.0" + } + }, + { + "tier": 8.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "8", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "125475.0" + } + }, + { + "tier": 9.0, + "symbol": "PARTI/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "9", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "500475.0" + } + } + ], "PENDLE/USDT:USDT": [ { "tier": 1.0, @@ -44148,6 +45184,127 @@ } } ], + "PLUME/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "PLUME/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "PNUT/USDC:USDC": [ { "tier": 1.0, @@ -50286,6 +51443,127 @@ } } ], + "SIREN/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "SIREN/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "SKL/USDT:USDT": [ { "tier": 1.0, @@ -57199,6 +58477,127 @@ } } ], + "TUT/USDT:USDT": [ + { + "tier": 1.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 0.0, + "maxNotional": 5000.0, + "maintenanceMarginRate": 0.02, + "maxLeverage": 25.0, + "info": { + "bracket": "1", + "initialLeverage": "25", + "notionalCap": "5000", + "notionalFloor": "0", + "maintMarginRatio": "0.02", + "cum": "0.0" + } + }, + { + "tier": 2.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 5000.0, + "maxNotional": 25000.0, + "maintenanceMarginRate": 0.025, + "maxLeverage": 20.0, + "info": { + "bracket": "2", + "initialLeverage": "20", + "notionalCap": "25000", + "notionalFloor": "5000", + "maintMarginRatio": "0.025", + "cum": "25.0" + } + }, + { + "tier": 3.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 25000.0, + "maxNotional": 200000.0, + "maintenanceMarginRate": 0.05, + "maxLeverage": 10.0, + "info": { + "bracket": "3", + "initialLeverage": "10", + "notionalCap": "200000", + "notionalFloor": "25000", + "maintMarginRatio": "0.05", + "cum": "650.0" + } + }, + { + "tier": 4.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 200000.0, + "maxNotional": 500000.0, + "maintenanceMarginRate": 0.1, + "maxLeverage": 5.0, + "info": { + "bracket": "4", + "initialLeverage": "5", + "notionalCap": "500000", + "notionalFloor": "200000", + "maintMarginRatio": "0.1", + "cum": "10650.0" + } + }, + { + "tier": 5.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 500000.0, + "maxNotional": 750000.0, + "maintenanceMarginRate": 0.125, + "maxLeverage": 4.0, + "info": { + "bracket": "5", + "initialLeverage": "4", + "notionalCap": "750000", + "notionalFloor": "500000", + "maintMarginRatio": "0.125", + "cum": "23150.0" + } + }, + { + "tier": 6.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 750000.0, + "maxNotional": 1500000.0, + "maintenanceMarginRate": 0.25, + "maxLeverage": 2.0, + "info": { + "bracket": "6", + "initialLeverage": "2", + "notionalCap": "1500000", + "notionalFloor": "750000", + "maintMarginRatio": "0.25", + "cum": "116900.0" + } + }, + { + "tier": 7.0, + "symbol": "TUT/USDT:USDT", + "currency": "USDT", + "minNotional": 1500000.0, + "maxNotional": 3000000.0, + "maintenanceMarginRate": 0.5, + "maxLeverage": 1.0, + "info": { + "bracket": "7", + "initialLeverage": "1", + "notionalCap": "3000000", + "notionalFloor": "1500000", + "maintMarginRatio": "0.5", + "cum": "491900.0" + } + } + ], "TWT/USDT:USDT": [ { "tier": 1.0, diff --git a/freqtrade/ft_types/backtest_result_type.py b/freqtrade/ft_types/backtest_result_type.py index 27cdb6126..b8ddbb4b6 100644 --- a/freqtrade/ft_types/backtest_result_type.py +++ b/freqtrade/ft_types/backtest_result_type.py @@ -1,4 +1,5 @@ -from typing import Any +from copy import deepcopy +from typing import Any, cast from typing_extensions import TypedDict @@ -15,11 +16,16 @@ class BacktestResultType(TypedDict): def get_BacktestResultType_default() -> BacktestResultType: - return { - "metadata": {}, - "strategy": {}, - "strategy_comparison": [], - } + return cast( + BacktestResultType, + deepcopy( + { + "metadata": {}, + "strategy": {}, + "strategy_comparison": [], + } + ), + ) class BacktestHistoryEntryType(BacktestMetadataType): diff --git a/freqtrade/optimize/backtesting.py b/freqtrade/optimize/backtesting.py index d2efc78b5..9a5e58c92 100644 --- a/freqtrade/optimize/backtesting.py +++ b/freqtrade/optimize/backtesting.py @@ -1792,6 +1792,7 @@ class Backtesting: dt_appendix, market_change_data=combined_res, analysis_results=self.analysis_results, + strategy_files={s.get_strategy_name(): s.__file__ for s in self.strategylist}, ) # Results may be mixed up now. Sort them so they follow --strategy-list order. diff --git a/freqtrade/optimize/optimize_reports/bt_storage.py b/freqtrade/optimize/optimize_reports/bt_storage.py index d0c5d7fb7..1e6a67e81 100644 --- a/freqtrade/optimize/optimize_reports/bt_storage.py +++ b/freqtrade/optimize/optimize_reports/bt_storage.py @@ -6,6 +6,7 @@ from zipfile import ZIP_DEFLATED, ZipFile from pandas import DataFrame +from freqtrade.configuration import sanitize_config from freqtrade.constants import LAST_BT_RESULT_FN from freqtrade.enums.runmode import RunMode from freqtrade.ft_types import BacktestResultType @@ -52,6 +53,7 @@ def store_backtest_results( *, market_change_data: DataFrame | None = None, analysis_results: dict[str, dict[str, DataFrame]] | None = None, + strategy_files: dict[str, str] | None = None, ) -> Path: """ Stores backtest results and analysis data in a zip file, with metadata stored separately @@ -85,6 +87,32 @@ def store_backtest_results( dump_json_to_file(stats_buf, stats_copy) zipf.writestr(json_filename.name, stats_buf.getvalue()) + config_buf = StringIO() + dump_json_to_file(config_buf, sanitize_config(config["original_config"])) + zipf.writestr(f"{base_filename.stem}_config.json", config_buf.getvalue()) + + for strategy_name, strategy_file in (strategy_files or {}).items(): + # Store the strategy file and its parameters + strategy_buf = BytesIO() + strategy_path = Path(strategy_file) + if not strategy_path.is_file(): + logger.warning(f"Strategy file '{strategy_path}' does not exist. Skipping.") + continue + with strategy_path.open("rb") as strategy_file_obj: + strategy_buf.write(strategy_file_obj.read()) + strategy_buf.seek(0) + zipf.writestr(f"{base_filename.stem}_{strategy_name}.py", strategy_buf.getvalue()) + strategy_params = strategy_path.with_suffix(".json") + if strategy_params.is_file(): + strategy_params_buf = BytesIO() + with strategy_params.open("rb") as strategy_params_obj: + strategy_params_buf.write(strategy_params_obj.read()) + strategy_params_buf.seek(0) + zipf.writestr( + f"{base_filename.stem}_{strategy_name}.json", + strategy_params_buf.getvalue(), + ) + # Add market change data if present if market_change_data is not None: market_change_name = f"{base_filename.stem}_market_change.feather" diff --git a/freqtrade/optimize/optimize_reports/optimize_reports.py b/freqtrade/optimize/optimize_reports/optimize_reports.py index c0188673a..e5b526779 100644 --- a/freqtrade/optimize/optimize_reports/optimize_reports.py +++ b/freqtrade/optimize/optimize_reports/optimize_reports.py @@ -18,7 +18,7 @@ from freqtrade.data.metrics import ( calculate_sortino, calculate_sqn, ) -from freqtrade.ft_types import BacktestResultType +from freqtrade.ft_types import BacktestResultType, get_BacktestResultType_default from freqtrade.util import decimals_per_coin, fmt_coin, get_dry_run_wallet @@ -587,11 +587,7 @@ def generate_backtest_stats( :param max_date: Backtest end date :return: Dictionary containing results per strategy and a strategy summary. """ - result: BacktestResultType = { - "metadata": {}, - "strategy": {}, - "strategy_comparison": [], - } + result: BacktestResultType = get_BacktestResultType_default() market_change = calculate_market_change(btdata, "close") metadata = {} pairlist = list(btdata.keys()) diff --git a/freqtrade/rpc/api_server/api_backtest.py b/freqtrade/rpc/api_server/api_backtest.py index 278922b7d..5d06e8a48 100644 --- a/freqtrade/rpc/api_server/api_backtest.py +++ b/freqtrade/rpc/api_server/api_backtest.py @@ -108,6 +108,9 @@ def __run_backtest_bg(btconfig: Config): ApiBG.bt["bt"].results, datetime.now().strftime("%Y-%m-%d_%H-%M-%S"), market_change_data=combined_res, + strategy_files={ + s.get_strategy_name(): s.__file__ for s in ApiBG.bt["bt"].strategylist + }, ) ApiBG.bt["bt"].results["metadata"][strategy_name]["filename"] = str(fn.stem) ApiBG.bt["bt"].results["metadata"][strategy_name]["strategy"] = strategy_name diff --git a/freqtrade/strategy/interface.py b/freqtrade/strategy/interface.py index 98e02cdd6..5cd873f23 100644 --- a/freqtrade/strategy/interface.py +++ b/freqtrade/strategy/interface.py @@ -132,6 +132,7 @@ class IStrategy(ABC, HyperStrategyMixin): stake_currency: str # container variable for strategy source code __source__: str = "" + __file__: str = "" # Definition of plot_config. See plotting documentation for more details. plot_config: dict = {} diff --git a/ft_client/freqtrade_client/__init__.py b/ft_client/freqtrade_client/__init__.py index f9a9baf16..32e91f3a1 100644 --- a/ft_client/freqtrade_client/__init__.py +++ b/ft_client/freqtrade_client/__init__.py @@ -1,7 +1,7 @@ from freqtrade_client.ft_rest_client import FtRestClient -__version__ = "2025.3-dev" +__version__ = "2025.4-dev" if "dev" in __version__: from pathlib import Path diff --git a/tests/conftest.py b/tests/conftest.py index b7e766b3e..06dd23f79 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -652,6 +652,7 @@ def get_default_conf(testdatadir): "trading_mode": "spot", "margin_mode": "", "candle_type_def": CandleType.SPOT, + "original_config": {}, } return configuration diff --git a/tests/optimize/test_optimize_reports.py b/tests/optimize/test_optimize_reports.py index d0c970b33..9fb5ccae9 100644 --- a/tests/optimize/test_optimize_reports.py +++ b/tests/optimize/test_optimize_reports.py @@ -1,5 +1,6 @@ import json import re +import shutil from datetime import timedelta from pathlib import Path from shutil import copyfile @@ -41,7 +42,7 @@ from freqtrade.optimize.optimize_reports.optimize_reports import ( from freqtrade.resolvers.strategy_resolver import StrategyResolver from freqtrade.util import dt_ts from freqtrade.util.datetime_helpers import dt_from_ts, dt_utc -from tests.conftest import CURRENT_TEST_STRATEGY +from tests.conftest import CURRENT_TEST_STRATEGY, log_has_re from tests.data.test_history import _clean_test_file @@ -253,8 +254,9 @@ def test_store_backtest_results(testdatadir, mocker): dump_mock = mocker.patch("freqtrade.optimize.optimize_reports.bt_storage.file_dump_json") zip_mock = mocker.patch("freqtrade.optimize.optimize_reports.bt_storage.ZipFile") data = {"metadata": {}, "strategy": {}, "strategy_comparison": []} - - store_backtest_results({"exportfilename": testdatadir}, data, "2022_01_01_15_05_13") + store_backtest_results( + {"exportfilename": testdatadir, "original_config": {}}, data, "2022_01_01_15_05_13" + ) assert dump_mock.call_count == 2 assert zip_mock.call_count == 1 @@ -264,7 +266,9 @@ def test_store_backtest_results(testdatadir, mocker): dump_mock.reset_mock() zip_mock.reset_mock() filename = testdatadir / "testresult.json" - store_backtest_results({"exportfilename": filename}, data, "2022_01_01_15_05_13") + store_backtest_results( + {"exportfilename": filename, "original_config": {}}, data, "2022_01_01_15_05_13" + ) assert dump_mock.call_count == 2 assert zip_mock.call_count == 1 assert isinstance(dump_mock.call_args_list[0][0][0], Path) @@ -272,9 +276,16 @@ def test_store_backtest_results(testdatadir, mocker): assert str(dump_mock.call_args_list[0][0][0]).startswith(str(testdatadir / "testresult")) -def test_store_backtest_results_real(tmp_path): +def test_store_backtest_results_real(tmp_path, caplog): data = {"metadata": {}, "strategy": {}, "strategy_comparison": []} - store_backtest_results({"exportfilename": tmp_path}, data, "2022_01_01_15_05_13") + config = { + "exportfilename": tmp_path, + "original_config": {}, + } + store_backtest_results( + config, data, "2022_01_01_15_05_13", strategy_files={"DefStrat": "NoFile"} + ) + assert log_has_re(r"Strategy file .* does not exist\. Skipping\.", caplog) zip_file = tmp_path / "backtest-result-2022_01_01_15_05_13.zip" assert zip_file.is_file() @@ -287,8 +298,19 @@ def test_store_backtest_results_real(tmp_path): fn = get_latest_backtest_filename(tmp_path) assert fn == "backtest-result-2022_01_01_15_05_13.zip" + strategy_test_dir = Path(__file__).parent.parent / "strategy" / "strats" + + shutil.copy(strategy_test_dir / "strategy_test_v3.py", tmp_path) + params_file = tmp_path / "strategy_test_v3.json" + with params_file.open("w") as f: + f.write("""{"strategy_name": "TurtleStrategyX5","params":{}}""") + store_backtest_results( - {"exportfilename": tmp_path}, data, "2024_01_01_15_05_25", market_change_data=pd.DataFrame() + config, + data, + "2024_01_01_15_05_25", + market_change_data=pd.DataFrame(), + strategy_files={"DefStrat": str(tmp_path / "strategy_test_v3.py")}, ) zip_file = tmp_path / "backtest-result-2024_01_01_15_05_25.zip" assert zip_file.is_file() @@ -298,6 +320,22 @@ def test_store_backtest_results_real(tmp_path): with ZipFile(zip_file, "r") as zipf: assert "backtest-result-2024_01_01_15_05_25.json" in zipf.namelist() assert "backtest-result-2024_01_01_15_05_25_market_change.feather" in zipf.namelist() + assert "backtest-result-2024_01_01_15_05_25_config.json" in zipf.namelist() + # strategy file is copied to the zip file + assert "backtest-result-2024_01_01_15_05_25_DefStrat.py" in zipf.namelist() + # compare the content of the strategy file + with zipf.open("backtest-result-2024_01_01_15_05_25_DefStrat.py") as strategy_file: + strategy_content = strategy_file.read() + with (strategy_test_dir / "strategy_test_v3.py").open("rb") as original_file: + original_content = original_file.read() + assert strategy_content == original_content + assert "backtest-result-2024_01_01_15_05_25_DefStrat.py" in zipf.namelist() + with zipf.open("backtest-result-2024_01_01_15_05_25_DefStrat.json") as pf: + params_content = pf.read() + with params_file.open("rb") as original_file: + original_content = original_file.read() + assert params_content == original_content + assert (tmp_path / LAST_BT_RESULT_FN).is_file() # Last file reference should be updated @@ -313,6 +351,7 @@ def test_write_read_backtest_candles(tmp_path): "exportfilename": tmp_path, "export": "signals", "runmode": "backtest", + "original_config": {}, } # test directory exporting sample_date = "2022_01_01_15_05_13"