from __future__ import annotations

from abc import ABC, abstractmethod
from enum import Enum
from typing import Dict, Optional, cast

import pandas as pd 
from pt_trading.results import BacktestResult
from pt_trading.trading_pair import TradingPair

NanoPerMin = 1e9


class PairsTradingFitMethod(ABC):
    TRADES_COLUMNS = [
        "time",
        "symbol",
        "side",
        "action",
        "price",
        "disequilibrium",
        "scaled_disequilibrium",
        "signed_scaled_disequilibrium",
        "pair",
    ]
    @staticmethod
    def create(config: Dict) -> PairsTradingFitMethod:
        import importlib
        fit_method_class_name = config.get("fit_method_class", None)
        assert fit_method_class_name is not None
        module_name, class_name = fit_method_class_name.rsplit(".", 1)
        module = importlib.import_module(module_name)
        fit_method = getattr(module, class_name)()
        return cast(PairsTradingFitMethod, fit_method)

    @abstractmethod
    def run_pair(
        self, pair: TradingPair, bt_result: BacktestResult
    ) -> Optional[pd.DataFrame]: ...

    @abstractmethod
    def reset(self) -> None: ...

    @abstractmethod
    def create_trading_pair(
        self,
        config: Dict,
        market_data: pd.DataFrame,
        symbol_a: str,
        symbol_b: str,
    ) -> TradingPair: ...

