Merge pull request #12679 from freqtrade/maint/binance_mig

Remove binance futures pair naming migration
This commit is contained in:
Matthias
2026-01-02 10:18:57 +01:00
committed by GitHub
3 changed files with 2 additions and 158 deletions

View File

@@ -1,8 +1,4 @@
from freqtrade.exchange import Exchange
from freqtrade.util.migrations.binance_mig import (
migrate_binance_futures_data,
migrate_binance_futures_names,
)
from freqtrade.util.migrations.funding_rate_mig import migrate_funding_fee_timeframe
@@ -10,7 +6,6 @@ def migrate_data(config, exchange: Exchange | None = None) -> None:
"""
Migrate persisted data from old formats to new formats
"""
migrate_binance_futures_data(config)
migrate_funding_fee_timeframe(config, exchange)
@@ -20,4 +15,5 @@ def migrate_live_content(config, exchange: Exchange | None = None) -> None:
Migrate database content from old formats to new formats
Used for dry/live mode.
"""
migrate_binance_futures_names(config)
# Currently not used
pass

View File

@@ -1,87 +0,0 @@
import logging
from packaging import version
from sqlalchemy import select
from freqtrade.constants import DOCS_LINK, Config
from freqtrade.enums import TradingMode
from freqtrade.exceptions import OperationalException
from freqtrade.persistence import KeyValueStore, Trade
from freqtrade.persistence.pairlock import PairLock
logger = logging.getLogger(__name__)
def migrate_binance_futures_names(config: Config):
"""
Migrate binance futures names in both database and data files.
This is needed because ccxt naming changed from "BTC/USDT" to "BTC/USDT:USDT"
"""
if not (
config.get("trading_mode", TradingMode.SPOT) == TradingMode.FUTURES
and config["exchange"]["name"] == "binance"
):
# only act on new futures
return
if KeyValueStore.get_int_value("binance_migration"):
# already migrated
return
import ccxt
if version.parse("2.6.26") > version.parse(ccxt.__version__):
raise OperationalException(
"Please follow the update instructions in the docs "
f"({DOCS_LINK}/updating/) to install a compatible ccxt version."
)
_migrate_binance_futures_db(config)
migrate_binance_futures_data(config)
KeyValueStore.store_value("binance_migration", 1)
def _migrate_binance_futures_db(config: Config):
logger.info("Migrating binance futures pairs in database.")
trades = Trade.get_trades([Trade.exchange == "binance", Trade.trading_mode == "FUTURES"]).all()
for trade in trades:
if ":" in trade.pair:
# already migrated
continue
new_pair = f"{trade.pair}:{trade.stake_currency}"
trade.pair = new_pair
for order in trade.orders:
order.ft_pair = new_pair
# Should symbol be migrated too?
# order.symbol = new_pair
Trade.commit()
pls = PairLock.session.scalars(select(PairLock).filter(PairLock.pair.notlike("%:%"))).all()
for pl in pls:
pl.pair = f"{pl.pair}:{config['stake_currency']}"
# print(pls)
# pls.update({'pair': concat(PairLock.pair,':USDT')})
Trade.commit()
logger.info("Done migrating binance futures pairs in database.")
def migrate_binance_futures_data(config: Config):
if not (
config.get("trading_mode", TradingMode.SPOT) == TradingMode.FUTURES
and config["exchange"]["name"] == "binance"
):
# only act on new futures
return
from freqtrade.data.history import get_datahandler
dhc = get_datahandler(config["datadir"], config["dataformat_ohlcv"])
paircombs = dhc.ohlcv_get_available_data(
config["datadir"], config.get("trading_mode", TradingMode.SPOT)
)
for pair, timeframe, candle_type in paircombs:
if ":" in pair:
# already migrated
continue
new_pair = f"{pair}:{config['stake_currency']}"
dhc.rename_futures_data(pair, new_pair, timeframe, candle_type)

View File

@@ -1,65 +0,0 @@
import shutil
import pytest
from freqtrade.persistence import Trade
from freqtrade.util.migrations import migrate_binance_futures_data, migrate_data
from freqtrade.util.migrations.binance_mig import migrate_binance_futures_names
from tests.conftest import create_mock_trades_usdt, log_has
def test_binance_mig_data_conversion(default_conf_usdt, tmp_path, testdatadir):
# call doing nothing (spot mode)
migrate_binance_futures_data(default_conf_usdt)
default_conf_usdt["trading_mode"] = "futures"
pair_old = "XRP_USDT"
pair_unified = "XRP_USDT_USDT"
futures_src = testdatadir / "futures"
futures_dst = tmp_path / "futures"
futures_dst.mkdir()
files = [
"-1h-mark.feather",
"-1h-futures.feather",
"-1h-funding_rate.feather",
"-1h-mark.feather",
]
# Copy files to tmpdir and rename to old naming
for file in files:
fn_after = futures_dst / f"{pair_old}{file}"
shutil.copy(futures_src / f"{pair_unified}{file}", fn_after)
default_conf_usdt["datadir"] = tmp_path
# Migrate files to unified namings
migrate_binance_futures_data(default_conf_usdt)
for file in files:
fn_after = futures_dst / f"{pair_unified}{file}"
assert fn_after.exists()
@pytest.mark.usefixtures("init_persistence")
def test_binance_mig_db_conversion(default_conf_usdt, fee, caplog):
# Does nothing in spot mode
migrate_binance_futures_names(default_conf_usdt)
create_mock_trades_usdt(fee, None)
for t in Trade.get_trades():
t.trading_mode = "FUTURES"
t.exchange = "binance"
Trade.commit()
default_conf_usdt["trading_mode"] = "futures"
migrate_binance_futures_names(default_conf_usdt)
assert log_has("Migrating binance futures pairs in database.", caplog)
def test_migration_wrapper(default_conf_usdt, mocker):
default_conf_usdt["trading_mode"] = "futures"
binmock = mocker.patch("freqtrade.util.migrations.migrate_binance_futures_data")
funding_mock = mocker.patch("freqtrade.util.migrations.migrate_funding_fee_timeframe")
migrate_data(default_conf_usdt)
assert binmock.call_count == 1
assert funding_mock.call_count == 1