#!/usr/bin/env python3 """ šŸ“Š Market Regime Checker - Quick Status Checks if market is Trending or Ranging """ import sys import MetaTrader5 as mt5 import pandas as pd import numpy as np from datetime import datetime, timezone SYMBOL = "XAUUSD" TIMEFRAME = mt5.TIMEFRAME_M15 ADX_THRESHOLD = 25 def calculate_adx(df, period=14): """Calculate ADX indicator using Wilder's smoothing (EWM)""" if len(df) < period + 1: return float('nan') alpha = 1 / period df['high_low'] = df['high'] - df['low'] df['high_close'] = np.abs(df['high'] - df['close'].shift()) df['low_close'] = np.abs(df['low'] - df['close'].shift()) df['true_range'] = df[['high_low', 'high_close', 'low_close']].max(axis=1) df['up_move'] = df['high'] - df['high'].shift() df['down_move'] = df['low'].shift() - df['low'] df['plus_dm'] = np.where((df['up_move'] > df['down_move']) & (df['up_move'] > 0), df['up_move'], 0) df['minus_dm'] = np.where((df['down_move'] > df['up_move']) & (df['down_move'] > 0), df['down_move'], 0) # Wilder's smoothing via EWM (adjust=False matches the classic formula) df['atr'] = df['true_range'].ewm(alpha=alpha, adjust=False).mean() df['plus_di'] = 100 * (df['plus_dm'].ewm(alpha=alpha, adjust=False).mean() / df['atr']) df['minus_di'] = 100 * (df['minus_dm'].ewm(alpha=alpha, adjust=False).mean() / df['atr']) sum_di = df['plus_di'] + df['minus_di'] df['dx'] = np.where(sum_di == 0, 0.0, 100 * np.abs(df['plus_di'] - df['minus_di']) / sum_di) df['adx'] = df['dx'].ewm(alpha=alpha, adjust=False).mean() return df['adx'].iloc[-1] def check_market_regime(): """Check current market regime""" print("=" * 70) print(f"šŸ“Š MARKET REGIME CHECK: {SYMBOL}") print("=" * 70) if not mt5.initialize(): print("āŒ MT5 initialization failed") return None try: tick = mt5.symbol_info_tick(SYMBOL) if not tick: print("āŒ Could not get price data") return None current_price = tick.bid timestamp = datetime.fromtimestamp(tick.time, tz=timezone.utc) print(f"\nšŸ’¹ Current Price: ${current_price:.2f}") print(f"ā° Time: {timestamp.strftime('%Y-%m-%d %H:%M:%S UTC')}") rates = mt5.copy_rates_from_pos(SYMBOL, TIMEFRAME, 0, 100) if rates is None or len(rates) == 0: print("āŒ Could not get historical data") return None df = rates if isinstance(rates, pd.DataFrame) else pd.DataFrame(rates) df['time'] = pd.to_datetime(df['time'], unit='s') adx = calculate_adx(df, period=14) if np.isnan(adx): print("āŒ ADX calculation failed (not enough data)") return None if adx < ADX_THRESHOLD: regime = "ranging" can_trade = False marker = "šŸ›‘" status = "RANGING MARKET" decision = "Trading BLOCKED" reason = f"ADX < {ADX_THRESHOLD} = No clear trend" advice = f"Wait for trending market (ADX ≄ {ADX_THRESHOLD})" else: regime = "trending" can_trade = True marker = "āœ…" status = "TRENDING MARKET" decision = "Trading ALLOWED" reason = f"ADX ≄ {ADX_THRESHOLD} = Strong trend" advice = "Good conditions for trading!" print(f"\nšŸ“ˆ REGIME ANALYSIS:") print(f" Regime: {status}") print(f" ADX: {adx:.1f}") print(f" Status: {marker} {regime.upper()}") print(f"\nšŸŽÆ TRADING DECISION:") print(f" {marker} {decision}") print(f" šŸ“Š {reason}") print(f" šŸ’” {advice}") print(f"\nšŸ“Š ADX SCALE:") print(" 0-20: Very Weak/Ranging āŒ") print(" 20-25: Weak/Ranging āš ļø") print(" 25-40: Trending āœ…") print(" 40+: Strong Trending āœ…āœ…") print(f" YOUR ADX: {adx:.1f} {'━' * min(int(adx / 2), 40)}") print("\n" + "=" * 70) return { 'regime': regime, 'adx': adx, 'can_trade': can_trade, 'price': current_price, 'timestamp': timestamp } finally: mt5.shutdown() if __name__ == "__main__": result = check_market_regime() sys.exit(0 if (result and result['can_trade']) else 1)