import os

DB_CONFIG = {
    'host': 'nlbotinterface.ru',
    'port': 3306,
    'user': 'bitcoin',
    'password': os.environ.get('MOEX_DB_PASSWORD', 'g49020007'),
    'database': 'bitcoin_tickers',
}

TIMEFRAMES = {'H1': 'H1', 'D1': 'D1', 'W1': 'W1'}

MOEX_TICKERS = [
    'ASTR', 'SBER', 'VTBR', 'ROSN', 'NVTK', 'PHOR',
    'SNGSP', 'PLZL', 'X5', 'MTSS', 'LKOH', 'GAZP',
    'MOEX', 'NSVZ',
]

CRYPTO_TICKERS = ['BITCOIN', 'BITCOINC', 'ZCASH']
FOREX_TICKERS = ['EURUSD']

TICKER_TYPES = {'moex': 'moex', 'forex': 'forex', 'crypto': 'crypto'}
MONITOR_TICKERS = MOEX_TICKERS + CRYPTO_TICKERS + FOREX_TICKERS


def get_market(ticker: str) -> str:
    """Определяет рынок тикера: 'moex', 'crypto' или 'forex'."""
    ticker = ticker.upper()
    if ticker in MOEX_TICKERS:
        return 'moex'
    if ticker in CRYPTO_TICKERS:
        return 'crypto'
    if ticker in FOREX_TICKERS:
        return 'forex'
    # По умолчанию — moex
    return 'moex'


# Per-market ATR конфигурация для target computation
# MOEX:  SL=3×ATR, TP=6×ATR (RR 1:2)
# Crypto: SL=4×ATR, TP=8×ATR (RR 1:2) — шире стоп из-за высокой волатильности
# Forex:  SL=2×ATR, TP=4×ATR (RR 1:2) — уже стоп из-за низкой волатильности
MARKET_TARGET_CONFIGS = {
    'moex':   {'atr_mult_sl': 3.0, 'atr_mult_tp': 6.0, 'max_bars': 200},
    'crypto': {'atr_mult_sl': 4.0, 'atr_mult_tp': 8.0, 'max_bars': 200},
    'forex':  {'atr_mult_sl': 2.0, 'atr_mult_tp': 4.0, 'max_bars': 200},
}


def get_target_config(ticker: str) -> dict:
    """Возвращает target config (SL/TP множители) для тикера по рынку."""
    market = get_market(ticker)
    return MARKET_TARGET_CONFIGS.get(market, MARKET_TARGET_CONFIGS['moex']).copy()
SAVE_DIR = 'models/saved'

RANDOM_SEED = 42
TEST_SIZE = 0.2
VALIDATION_SIZE = 0.1
RF_DEFAULTS = {'n_estimators': 200, 'max_depth': 10, 'min_samples_split': 5,
               'min_samples_leaf': 2, 'random_state': RANDOM_SEED, 'n_jobs': -1}

RL_CONFIG = {
    'n_epochs': 20,
    'episode_size': 2000,
    'atr_mult_sl': 1.5,
    'atr_mult_tp': 3.0,
    'hidden_dim': 128,
    'lr': 1e-3,
    'gamma': 0.99,
    'epsilon_start': 1.0,
    'epsilon_end': 0.01,
    'epsilon_decay_steps': 10000,
    'buffer_capacity': 50000,
    'batch_size': 128,
    'target_update': 200,
}

TARGET_CONFIG = MARKET_TARGET_CONFIGS['moex'].copy()  # по умолчанию MOEX

# Параметры риск-менеджмента для TradeManager
RISK_CONFIG = {
    'risk_per_trade': 0.01,       # 1% риска на сделку
    'sl_mult': 3.0,                # множитель ATR для SL (3×ATR)
    'tp_mult': 6.0,                # множитель ATR для TP (6×ATR, RR 1:2)
    'reentry_delay_hours': 4,      # защита от каскада: не входить N часов после SL
    'time_stop_hours': 48,         # принудительное закрытие через N часов
    'weekend_filter': True,        # не торговать в выходные
    'max_atr_ratio': 0.05,         # макс ATR в % от цены (защита от битых данных)
}

# Per-ticker асимметричные пороги (v12.5)
# Long: вероятность BUY при которой генерируется сигнал
# Short: вероятность SELL при которой генерируется сигнал
# Значения подобраны эмпирически через opt_th sweep по каждому тикеру
TICKER_THRESHOLDS = {
    'ASTR':  {'long': 0.48, 'short': 0.38},
    'GAZP':  {'long': 0.48, 'short': 0.48},
    'LKOH':  {'long': 0.48, 'short': 0.48},
    'MOEX':  {'long': 0.48, 'short': 0.37},
    'MTSS':  {'long': 0.48, 'short': 0.31},
    'NSVZ':  {'long': 0.48, 'short': 0.30},
    'NVTK':  {'long': 0.48, 'short': 0.31},
    'PHOR':  {'long': 0.48, 'short': 0.31},
    'PLZL':  {'long': 0.48, 'short': 0.30},
    'ROSN':  {'long': 0.48, 'short': 0.30},
    'SBER':  {'long': 0.48, 'short': 0.40},
    'SNGSP': {'long': 0.48, 'short': 0.44},
    'VTBR':  {'long': 0.48, 'short': 0.48},
    'X5':    {'long': 0.48, 'short': 0.46},
}
# Ticker-specific class_weight для short RF (FN penalty)
# v3: снижены с 4.5→3.0 и 3.5→2.5 для баланса accuracy vs recall
TICKER_SHORT_WEIGHTS = {
    'ASTR':  3.0, 'GAZP':  3.0, 'LKOH':  3.0,
    'MOEX':  2.5, 'MTSS':  2.0, 'NSVZ':  2.0,
    'NVTK':  2.5, 'PHOR':  2.5, 'PLZL':  2.0,
    'ROSN':  2.5, 'SBER':  3.0, 'SNGSP': 3.0,
    'VTBR':  3.0, 'X5':    3.0,
}
# Ticker-specific scale_pos_weight multiplier для LONG XGBoost.
# Значения: 1.5–3.0. Выше — для тикеров с сильным дисбалансом outcome_long.
# Снимает cap scale_pos_long с 5→15, плюс множитель для усиления сигнала.
TICKER_LONG_WEIGHTS = {
    'ASTR': 3.0,  'GAZP': 2.0,  'LKOH': 2.5,
    'MOEX': 2.5,  'MTSS': 3.0,  'NSVZ': 2.5,
    'NVTK': 1.5,  'PHOR': 2.5,  'PLZL': 3.0,
    'ROSN': 2.5,  'SBER': 2.0,  'SNGSP': 3.0,
    'VTBR': 2.0,  'X5':   3.0,
}

# Default thresholds and weights (consolidated)
DEFAULT_CONFIG = {
    'long_threshold': 0.48,
    'short_threshold': 0.42,
    'short_weight': 3.0,
    'long_weight': 2.0,
}

# Backward compatibility aliases
DEFAULT_LONG_TH = DEFAULT_CONFIG['long_threshold']
DEFAULT_SHORT_TH = DEFAULT_CONFIG['short_threshold']
DEFAULT_SHORT_WEIGHT = DEFAULT_CONFIG['short_weight']
DEFAULT_LONG_WEIGHT = DEFAULT_CONFIG['long_weight']

# Rolling WinRate filter — динамическая блокировка сигналов
# Если rolling WR направления ниже breakeven — сигнал отменяется
# +2% запас, как в find_best_thr
# Значения по умолчанию — для MOEX (SL=3, TP=6 → breakeven=3/9+0.02=0.353)
SL_MULT = MARKET_TARGET_CONFIGS['moex']['atr_mult_sl']  # 3.0
TP_MULT = MARKET_TARGET_CONFIGS['moex']['atr_mult_tp']  # 6.0
ROLLING_WR_BREAKEVEN = SL_MULT / (SL_MULT + TP_MULT) + 0.02  # 3/9+0.02 = 0.353
ROLLING_WR_MIN_SAMPLES = 30  # минимум resolved свечей для статистики

try:
    import torch
    DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
except ImportError:
    DEVICE = 'cpu'

# Feature ranking — используется directional model с --top-k.
# Актуальный рейтинг: TOP_FEATURES_BY_RANK в main.py.

# Конфигурация моделей
MODEL_CONFIG = {
    'rf': {
        'n_estimators': 200,
        'max_depth': 10,
        'random_state': RANDOM_SEED,
        'n_jobs': -1,
        'class_weight': 'balanced'
    },
    'xgb': {
        'n_estimators': 300,
        'max_depth': 6,
        'learning_rate': 0.1,
        'subsample': 0.8,
        'colsample_bytree': 0.8,
        'eval_metric': 'logloss',
        'random_state': RANDOM_SEED,
        'n_jobs': -1,
        'verbosity': 0,
        'scale_pos_weight': 2.5,  # Фаза 6: штраф за пропуск редкого класса
    },
    'lightgbm': {
        'n_estimators': 500,
        'max_depth': 8,
        'learning_rate': 0.05,
        'subsample': 0.8,
        'colsample_bytree': 0.8,
        'reg_alpha': 0.1,
        'reg_lambda': 0.1,
        'min_child_samples': 20,
        'random_state': RANDOM_SEED,
        'n_jobs': -1,
        'verbosity': -1,
        'scale_pos_weight': 2.5,  # Фаза 6: штраф за пропуск редкого класса
    }
}

# Топ фичей (вынесено из main.py для удобства изменения)
TOP_FEATURES_BY_RANK = [
    'atr_pct', 'bb_width', 'close_to_sma_50', 'macd',
    'bb_width_x_atr_pct', 'return_20', 'macd_hist', 'bb_width_x_rsi',
    'cts50_x_ret20', 'close_to_sma_20', 'strength_trend', 'rsi',
    'trend_signal', 'bb_position', 'close_to_sma_10', 'volume_ratio',
    'macd_signal_accel', 'atr_pct_x_vol_ratio', 'rsi_x_bb_pos', 'signal_strength',
    'return_1', 'bb_signal', 'directional_bias', 'rsi_signal_accel',
    'directional_bias_accel', 'close_to_sma_5', 'return_5', 'momentum_signal',
    'rsi_signal', 'macd_signal', 'hh_streak', 'll_streak',
    'volume_signal', 'engulfing', 'doji',
]
