deeper / ai.py
Dooratre's picture
Update ai.py
c845e0a verified
import requests
import time
import pytz
import json
from datetime import datetime, timedelta
from timeframe import fetch_financial_data
def get_times():
"""Get current time in different financial centers"""
# Define the time zones
greenwich_tz = pytz.timezone('GMT')
london_tz = pytz.timezone('Europe/London')
newyork_tz = pytz.timezone('America/New_York')
tokyo_tz = pytz.timezone('Asia/Tokyo')
sydney_tz = pytz.timezone('Australia/Sydney')
# Get current UTC time
utc_now = datetime.now(pytz.utc)
# Convert to each timezone
greenwich_time = utc_now.astimezone(greenwich_tz)
london_time = utc_now.astimezone(london_tz)
newyork_time = utc_now.astimezone(newyork_tz)
tokyo_time = utc_now.astimezone(tokyo_tz)
sydney_time = utc_now.astimezone(sydney_tz)
# Format the times
time_format = "%Y-%m-%d %H:%M:%S %Z%z"
times = {
"Greenwich": greenwich_time.strftime(time_format),
"London": london_time.strftime(time_format),
"New York": newyork_time.strftime(time_format),
"Tokyo": tokyo_time.strftime(time_format),
"Sydney": sydney_time.strftime(time_format)
}
return times
def chat_with_ai(chat_history, temperature=0.4):
"""Send chat history to AI and get response"""
url = "https://corvo-ai-xx-ry.hf.space/chat"
headers = {
"Content-Type": "application/json",
}
payload = {
"chat_history": chat_history,
"temperature": temperature,
}
max_retries = 3
retry_delay = 5
for attempt in range(max_retries):
try:
response = requests.post(url, headers=headers, json=payload, timeout=120)
response.raise_for_status()
result = response.json()
return result.get("assistant_response", "No response received.")
except Exception as e:
if attempt < max_retries - 1:
time.sleep(retry_delay)
print(f"Retry {attempt+1}: Communication error - {str(e)}")
else:
print(f"Final attempt failed: {str(e)}")
return "عذراً، واجهت مشكلة في الاتصال. يرجى المحاولة مرة أخرى لاحقاً. 🙁"
def fetch_pair_data(pair):
"""
Fetch data for a pair in multiple timeframes with appropriate time ranges:
- 15m: 3 days of data
- 5min: 1 day of data
Returns data for both timeframes or only what's available
"""
now = datetime.now()
# Determine if we need to add =X suffix
special_symbols = ["DX-Y.NYB", "GC=F", "^SPX", "WTI", "^TNX", "^FTSE"]
if pair in special_symbols:
symbol = pair # Use symbol as is, without appending =X
else:
symbol = f"{pair}=X" # Append =X for forex pairs
print(f"Fetching data for {symbol}...")
timeframes = {}
# Fetch 15-minute data (3 days)
try:
fifteen_min_start = now - timedelta(days=3)
fifteen_min_data = fetch_financial_data(
symbol=symbol,
start_date=fifteen_min_start,
end_date=now,
interval="15m"
)
if fifteen_min_data['success']:
timeframes["15m"] = fifteen_min_data
else:
print(f"⚠️ Failed to fetch 15m data for {pair}: {fifteen_min_data['message']}")
except Exception as e:
print(f"⚠️ Error fetching 15m data for {pair}: {str(e)}")
# Wait between requests to avoid rate limiting
time.sleep(1)
# Fetch 5-minute data (1 day)
try:
five_min_start = now - timedelta(days=1)
five_min_data = fetch_financial_data(
symbol=symbol,
start_date=five_min_start,
end_date=now,
interval="5min"
)
if five_min_data['success']:
timeframes["5min"] = five_min_data
else:
print(f"⚠️ Failed to fetch 5min data for {pair}: {five_min_data['message']}")
# Try 1-hour data as fallback if 5min fails
try:
hour_start = now - timedelta(days=7) # Get a week of hourly data
hour_data = fetch_financial_data(
symbol=symbol,
start_date=hour_start,
end_date=now,
interval="60m"
)
if hour_data['success']:
timeframes["1h"] = hour_data
print(f"✅ Successfully fetched fallback 1h data for {pair}")
except Exception as e:
print(f"⚠️ Error fetching fallback 1h data for {pair}: {str(e)}")
except Exception as e:
print(f"⚠️ Error fetching 5min data for {pair}: {str(e)}")
# Try 1-hour data as fallback
try:
hour_start = now - timedelta(days=7) # Get a week of hourly data
hour_data = fetch_financial_data(
symbol=symbol,
start_date=hour_start,
end_date=now,
interval="60m"
)
if hour_data['success']:
timeframes["1h"] = hour_data
print(f"✅ Successfully fetched fallback 1h data for {pair}")
except Exception as e:
print(f"⚠️ Error fetching fallback 1h data for {pair}: {str(e)}")
return timeframes
def analyze_forex_pairs(pairs, description, deals=""):
"""Main function to analyze a list of forex pairs"""
print(f"Analyzing forex pairs: {', '.join(pairs)}")
# Step 1: Get current times in financial centers
market_times = get_times()
times_text = "\n".join([f"{k}: {v}" for k, v in market_times.items()])
# Step 2: Fetch data for all pairs
pairs_data = {}
for pair in pairs:
print(f"📊 Fetching data for {pair}...")
pairs_data[pair] = fetch_pair_data(pair)
time.sleep(1) # Small delay between requests
# Prepare system prompt with market times and group context
system_prompt = f"""
You are a Senior Forex Analyst and Precision Entry Strategist specializing in intraday relationship-driven technical analysis.
📆 **Current Market Times**:
{times_text}
🕐 **All analysis is based on Greenwich Mean Time (GMT)** to ensure accurate tracking of session overlaps.
📊 **Session Times (GMT):**
| ⏰ **التوقيت (GMT)** | 💥 **الجلسات المتداخلة** | 🌐 **العملات المستفيدة** | 📝 **ملاحظات** |
| ------------------- | ------------------------ | --------------------------------------- | ------------------------------------------- |
| **00:00 – 02:00** | **سيدني + طوكيو** | AUD, NZD, JPY | بداية حركة آسيا – دعم للتقنيات المبكرة |
| **01:00 – 03:00** | **ويلينغتون + طوكيو** | NZD, JPY | نشاط خفيف – مفيد لتداول NZDJPY |
| **01:00 – 04:00** | **سنغافورة + طوكيو** | JPY, AUD, NZD | حجم تداول متوسط – بداية سيولة للسوق الآسيوي |
| **06:00 – 08:00** | **فرانكفورت + طوكيو** | EUR, JPY | بداية الزخم الأوروبي – تحركات مبكرة |
| **07:00 – 09:00** | **لندن + طوكيو** | GBP, JPY, EUR, USD, AUD, NZD | ⚡ سيولة عالية جدًا – ممتاز للسكالبينج |
| **07:00 – 10:00** | **زيورخ + لندن** | CHF, EUR, GBP | جلسة أوروبا الكاملة – نشاط مؤسسات |
| **08:00 – 09:00** | **لندن + سنغافورة** | GBP, SGD, JPY | بعض الفرص على GBPJPY / GBPSGD |
| **12:00 – 16:00** | **لندن + نيويورك** | ✅ USD, GBP, EUR, CHF, XAU, المؤشرات | أقوى فترة في اليوم – تدفقات مؤسسات |
| **13:00 – 15:00** | **نيويورك + فرانكفورت** | USD, EUR | نشاط البيانات الاقتصادية الأمريكية |
| **13:00 – 16:00** | **نيويورك + زيورخ** | USD, CHF | مفيد لتداول USDCHF – حركات واضحة |
| **14:00 – 17:00** | **نيويورك + شيكاغو** | USD, الذهب (XAU), النفط (WTI), المؤشرات | العقود الأمريكية تبدأ بالحركة القوية |
| **22:00 – 00:00** | **نيويورك + سيدني** | USD, AUD, XAU | هدوء نسبي – مناسب لتحليل ما قبل الآسيوية |
🔁 Important Session Overlaps (High Liquidity):
⏱️ Tokyo + Sydney: from 00:00 to 07:00
⏱️ Tokyo + London: from 07:00 to 09:00
⏱️ London + New York (most critical): from 12:00 to 16:00
🚨🚨🚨 **EXTREMELY IMPORTANT RULE (DO NOT IGNORE):**
⛔ ONLY send a signal if the current time is BETWEEN the start and end of one of the defined session overlap periods (inclusive). That means every minute from the start time to the end time is valid.
⛔ This is NOT optional — it is a **mandatory condition**.
⚠️ **NO signals allowed even if two sessions are open, UNLESS it is during these clearly defined overlap periods**.
🟥🟥🟥 **If the time is NOT during 00:00–07:00, 07:00–09:00, or 12:00–16:00 GMT — DO NOT send a signal. Period.**
ALL THIS POINTS YOU CAN SKIP IT JUST IF THERE 100% SUCCES TRADE SIGNAL (MAKE SURE TO TELL ME I GIVE YOU SIGNAL NOW WITH 1 SESSION OPEN BECAUSE IT IS 100% SUCCES)
✅ Priority is given to the overlap of **London + New York**, as it provides the clearest and strongest market movement.
📌 **Pairs Under Review**:
{pairs}
📢 **Group Overview**:
{description}
📈 **User's Current Open Trades**:
{deals}
🚫 **You are not allowed to create a new signal on any pair that already has an open trade** — wait until the existing trade is closed.
---
🎯 **Your Objective**
You must analyze the available timeframe data to determine whether there is a clean technical setup supporting a potential **40 to 70 pip move** with minimal drawdown.
Your analysis must always be based on **inter-pair and inter-asset relationships** — never analyze a single pair in isolation.
📉 Analysis should consider recent market conditions and price action from the timeframes available.
---
📊 **Entry Criteria**
✅ **Confirmation Candle**
- Must be one of the following (visible on the chart):
• Bullish/Bearish Engulfing
• Marubozu
• Pin Bar
- The pattern must be clearly visible on the available charts
❗ If no confirmation candle appears from this list, **do not send a signal** — wait for one to appear.
🔁 **Market Trend Direction**
- A clear short-term trend must be present on the available charts
- It must align with directional bias based on group correlation
- RSI:
• Buy setups: between 45–70
• Sell setups: between 30–55
- Volume: Preferably above average
- Candle Quality:
• The last 3 candles must NOT be choppy, wick-heavy, or weak
- Momentum Exhaustion Filter:
• Avoid entry if the last 5 candles moved more than 100 pips in total
📍 **Support/Resistance Zone Proximity**
- Entry must occur near or in reaction to a clearly defined zone
- Price must be within 20 pips of the zone
💼 **Risk-to-Reward Management**
- Minimum R:R = 2.0
- Target profit must be between 40 and 70 pips
---
🧠 **Mandatory Output Format (Strict):**
```xml
<Session>
put herr is there any session openinig ?
</Session>
<MarketContext>
Explain the current inter-pair relationships, such as EURUSD vs DXY or USDJPY vs US10Y. Mention any macro market flow if present.
</MarketContext>
<Analysis>
Use the available chart data to assess candle structure, market behavior, confirmation pattern, volume, RSI, etc.
Be precise and professional. Only highlight clean low-risk entry points.
</Analysis>
<Prediction>
State the expected direction (bullish or bearish), and whether a 40–70 pip move is likely within the next 1–3 hours based on current correlations and technicals.
</Prediction>
<Advice>
Advise the trader to wait, monitor, or prepare for entry. Only suggest action if the structure is clean, the volume confirms, and the signal is valid.
</Advice>
<Invalidation>
Clearly define what would invalidate the setup, such as a structural break, volume drop, or correlation failure.
</Invalidation>
🚨🚨🚨 MANDATORY FINAL STEP:
📩 Your response MUST ALWAYS end with either:
✅ A full signal using:
<signal>
<pair>PAIR_NAME</pair>
<type>Buy or Sell</type>
<entry>Ideal entry price</entry>
<stop_loss>Technical stop loss</stop_loss>
<take_profit>Target profit (40–70 pips)</take_profit>
<duration>1–3 hours (or momentum-based)</duration>
<reason>
Detailed technical reasoning including candle type, zone interaction, volume confirmation, and group correlation support.
</reason>
</signal>
❌ OR a proper wait explanation using:
<wait>
Explain clearly what is missing or risky: no confirmation candle, weak correlation, low volume, unclear structure, or an existing trade on the pair.
Also include if the current time is outside the required session overlap.
</wait>
⚠️ You are NOT allowed to give analysis or predictions without wrapping the output in <wait> or <signal> — it is mandatory to close with one of these tags in every single response.
# Build chat history with system prompt"""
chat_history = [
{"role": "system", "content": system_prompt}
]
# Add data for each pair as separate user messages for each timeframe
for pair, timeframes_data in pairs_data.items():
pair_data_added = False
# Add data for each available timeframe
for timeframe in ["15m", "5min", "1h"]:
if timeframe in timeframes_data and timeframes_data[timeframe]['success']:
chat_history.append({
"role": "user",
"content": f"**{pair} - {timeframe} Timeframe**\n\n{timeframes_data[timeframe]['table']}\n\n**Statistics:**\n{timeframes_data[timeframe]['stats']}\n\n**Meta Info:**\n{timeframes_data[timeframe]['meta_info']}"
})
pair_data_added = True
# If no data was added for this pair, inform the AI
if not pair_data_added:
chat_history.append({
"role": "user",
"content": f"**{pair} - No data available**\nUnable to fetch reliable data for this pair at the moment. Please analyze the other pairs in the group and mention that data for {pair} is currently unavailable."
})
# Get AI analysis
print("Sending data to AI for analysis...")
try:
analysis = chat_with_ai(chat_history)
print(analysis)
print("Analysis complete!")
return analysis
except Exception as e:
error_msg = f"Error during AI analysis: {str(e)}"
print(error_msg)
# If the payload is too large, try simplifying it
if len(str(chat_history)) > 10000000000: # If chat history is very large
print("Chat history is too large. Simplifying data...")
simplified_chat_history = [
{"role": "system", "content": system_prompt}
]
for pair, timeframes_data in pairs_data.items():
if "15m" in timeframes_data and timeframes_data["15m"]["success"]:
# Only include table without stats and meta info
simplified_chat_history.append({
"role": "user",
"content": f"**{pair} - 15m Timeframe**\n\n{timeframes_data['15m']['table']}"
})
elif "1h" in timeframes_data and timeframes_data["1h"]["success"]:
# Fall back to hourly data if 15m isn't available
simplified_chat_history.append({
"role": "user",
"content": f"**{pair} - 1h Timeframe**\n\n{timeframes_data['1h']['table']}"
})
try:
print("Retrying with simplified data...")
analysis = chat_with_ai(simplified_chat_history)
print("Analysis with simplified data complete!")
return analysis
except Exception as e2:
return f"Error during analysis even with simplified data: {str(e2)}\n\nPlease try again later with fewer pairs or a shorter timeframe."
return error_msg