diff --git a/mt5bridge_ccxt/timeframe.py b/mt5bridge_ccxt/timeframe.py new file mode 100644 index 0000000..7011c36 --- /dev/null +++ b/mt5bridge_ccxt/timeframe.py @@ -0,0 +1,70 @@ +"""Timeframe conversion between CCXT and MT5Bridge formats. + +CCXT uses short lowercase strings: "1m", "5m", "15m", "30m", "1h", "4h", "1d" +MT5Bridge uses prefixed identifiers: "TIMEFRAME_M1", "TIMEFRAME_M5", ... +""" + +# CCXT format -> MT5Bridge format +CCXT_TO_MT5 = { + "1m": "TIMEFRAME_M1", + "5m": "TIMEFRAME_M5", + "15m": "TIMEFRAME_M15", + "30m": "TIMEFRAME_M30", + "1h": "TIMEFRAME_H1", + "4h": "TIMEFRAME_H4", + "1d": "TIMEFRAME_D1", +} + +# MT5Bridge format -> CCXT format (reverse mapping) +MT5_TO_CXT = {v: k for k, v in CCXT_TO_MT5.items()} + +# Timeframe duration in seconds (used for time-based queries) +CCXT_TIMEFRAME_SECONDS = { + "1m": 60, + "5m": 300, + "15m": 900, + "30m": 1800, + "1h": 3600, + "4h": 14400, + "1d": 86400, +} + + +def to_mt5(timeframe): + """Convert CCXT timeframe string to MT5Bridge format. + + Args: + timeframe: CCXT timeframe (e.g. "1h", "1d") + + Returns: + str: MT5Bridge timeframe (e.g. "TIMEFRAME_H1") + + Raises: + ValueError: if timeframe is not supported + """ + if timeframe not in CCXT_TO_MT5: + raise ValueError( + f"Unsupported timeframe '{timeframe}'. " + f"Supported: {sorted(CCXT_TO_MT5.keys())}" + ) + return CCXT_TO_MT5[timeframe] + + +def to_ccxt(timeframe): + """Convert MT5Bridge timeframe string to CCXT format. + + Args: + timeframe: MT5Bridge timeframe (e.g. "TIMEFRAME_H1") + + Returns: + str: CCXT timeframe (e.g. "1h") + + Raises: + ValueError: if timeframe is unknown + """ + if timeframe not in MT5_TO_CXT: + raise ValueError( + f"Unknown MT5Bridge timeframe '{timeframe}'. " + f"Supported: {sorted(MT5_TO_CXT.values())}" + ) + return MT5_TO_CXT[timeframe]