fix: stage missing code review fixes (7 files)
Files were edited but not staged in earlier commits: - adaptive_rhythm_manager.py: mt→mt5, pytz→timezone, get_volatility_level, shutdown() - check_market_regime.py: ADX_THRESHOLD, Wilder EWM, try/finally, UTC timestamp, sys import - check_system_status.py: remove duplicate cursor.execute - drawdown_protection.py: float(inf), persist pause state, DB save_setting, Markdown fix - performance_analysis.py: KeyError export fix, profit factor, drawdown positive, SQL filter - performance_analysis_simple.py: fromisoformat, numeric bin sort, profit factor - trading_dashboard.py: st.rerun(), session_state auto-refresh, pathlib DB path, errors=coerce Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+80
-80
@@ -4,38 +4,42 @@
|
||||
Checks if market is Trending or Ranging
|
||||
"""
|
||||
|
||||
import MetaTrader5 as mt
|
||||
import sys
|
||||
import MetaTrader5 as mt5
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
|
||||
SYMBOL = "XAUUSD"
|
||||
TIMEFRAME = mt.TIMEFRAME_M15
|
||||
TIMEFRAME = mt5.TIMEFRAME_M15
|
||||
ADX_THRESHOLD = 25
|
||||
|
||||
def calculate_adx(df, period=14):
|
||||
"""Calculate ADX indicator"""
|
||||
"""Calculate ADX indicator using Wilder's smoothing (EWM)"""
|
||||
if len(df) < period + 1:
|
||||
return float('nan')
|
||||
|
||||
alpha = 1 / period
|
||||
|
||||
# True Range
|
||||
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)
|
||||
|
||||
# Directional Movement
|
||||
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)
|
||||
|
||||
# Smoothed values
|
||||
df['atr'] = df['true_range'].rolling(window=period).mean()
|
||||
df['plus_di'] = 100 * (df['plus_dm'].rolling(window=period).mean() / df['atr'])
|
||||
df['minus_di'] = 100 * (df['minus_dm'].rolling(window=period).mean() / df['atr'])
|
||||
# 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'])
|
||||
|
||||
# ADX
|
||||
df['dx'] = 100 * np.abs(df['plus_di'] - df['minus_di']) / (df['plus_di'] + df['minus_di'])
|
||||
df['adx'] = df['dx'].rolling(window=period).mean()
|
||||
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]
|
||||
|
||||
@@ -46,88 +50,84 @@ def check_market_regime():
|
||||
print(f"📊 MARKET REGIME CHECK: {SYMBOL}")
|
||||
print("=" * 70)
|
||||
|
||||
# Initialize MT5
|
||||
if not mt.initialize():
|
||||
if not mt5.initialize():
|
||||
print("❌ MT5 initialization failed")
|
||||
return None
|
||||
|
||||
# Get current price
|
||||
tick = mt.symbol_info_tick(SYMBOL)
|
||||
if not tick:
|
||||
print("❌ Could not get price data")
|
||||
mt.shutdown()
|
||||
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)
|
||||
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')}")
|
||||
print(f"\n💹 Current Price: ${current_price:.2f}")
|
||||
print(f"⏰ Time: {timestamp.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
||||
|
||||
# Get historical data for ADX calculation
|
||||
rates = mt.copy_rates_from_pos(SYMBOL, TIMEFRAME, 0, 100)
|
||||
if rates is None or len(rates) == 0:
|
||||
print("❌ Could not get historical data")
|
||||
mt.shutdown()
|
||||
return None
|
||||
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 = pd.DataFrame(rates)
|
||||
df['time'] = pd.to_datetime(df['time'], unit='s')
|
||||
df = rates if isinstance(rates, pd.DataFrame) else pd.DataFrame(rates)
|
||||
df['time'] = pd.to_datetime(df['time'], unit='s')
|
||||
|
||||
# Calculate ADX
|
||||
adx = calculate_adx(df, period=14)
|
||||
adx = calculate_adx(df, period=14)
|
||||
|
||||
# Determine regime
|
||||
if adx < 25:
|
||||
regime = "ranging"
|
||||
can_trade = False
|
||||
symbol = "🛑"
|
||||
status = "RANGING MARKET"
|
||||
decision = "Trading BLOCKED"
|
||||
reason = "ADX < 25 = No clear trend"
|
||||
advice = "Wait for trending market (ADX ≥ 25)"
|
||||
else:
|
||||
regime = "trending"
|
||||
can_trade = True
|
||||
symbol = "✅"
|
||||
status = "TRENDING MARKET"
|
||||
decision = "Trading ALLOWED"
|
||||
reason = "ADX ≥ 25 = Strong trend"
|
||||
advice = "Good conditions for trading!"
|
||||
if np.isnan(adx):
|
||||
print("❌ ADX calculation failed (not enough data)")
|
||||
return None
|
||||
|
||||
print(f"\n📈 REGIME ANALYSIS:")
|
||||
print(f" Regime: {status}")
|
||||
print(f" ADX: {adx:.1f}")
|
||||
print(f" Status: {symbol} {regime.upper()}")
|
||||
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🎯 TRADING DECISION:")
|
||||
print(f" {symbol} {decision}")
|
||||
print(f" 📊 {reason}")
|
||||
print(f" 💡 {advice}")
|
||||
print(f"\n📈 REGIME ANALYSIS:")
|
||||
print(f" Regime: {status}")
|
||||
print(f" ADX: {adx:.1f}")
|
||||
print(f" Status: {marker} {regime.upper()}")
|
||||
|
||||
# Visual indicator
|
||||
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} {'━' * int(adx/2)}")
|
||||
print(f"\n🎯 TRADING DECISION:")
|
||||
print(f" {marker} {decision}")
|
||||
print(f" 📊 {reason}")
|
||||
print(f" 💡 {advice}")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
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)}")
|
||||
|
||||
mt.shutdown()
|
||||
print("\n" + "=" * 70)
|
||||
|
||||
return {
|
||||
'regime': regime,
|
||||
'adx': adx,
|
||||
'can_trade': can_trade,
|
||||
'price': current_price,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
|
||||
finally:
|
||||
mt5.shutdown()
|
||||
|
||||
return {
|
||||
'regime': regime,
|
||||
'adx': adx,
|
||||
'can_trade': can_trade,
|
||||
'price': current_price,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
result = check_market_regime()
|
||||
|
||||
if result:
|
||||
import sys
|
||||
sys.exit(0 if result['can_trade'] else 1)
|
||||
sys.exit(0 if (result and result['can_trade']) else 1)
|
||||
|
||||
Reference in New Issue
Block a user