Alimcptv / src /tradingview_monitor.py
Alikhani099961's picture
Upload 8 files
2755a1d verified
import time
import json
import requests
import smtplib
import schedule
import threading
import streamlit as st
from email.mime.text import MimeText
from email.mime.multipart import MimeMultipart
from datetime import datetime
import pandas as pd
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service
import logging
# تنظیم لاگ
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TradingViewMonitor:
def __init__(self):
"""
کلاس نظارت بر TradingView
"""
self.driver = None
self.is_monitoring = False
self.monitoring_thread = None
self.indicators_data = {}
self.last_signals = {}
self.notification_settings = {
"email": {
"enabled": False,
"smtp_server": "",
"smtp_port": 587,
"username": "",
"password": "",
"recipient": "",
"subject": "TradingView Signal Alert"
},
"webhook": {
"enabled": False,
"url": "",
"method": "POST",
"payload": {}
}
}
def setup_driver(self):
"""
راه‌اندازی درایور Chrome برای TradingView
"""
try:
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
service = Service(ChromeDriverManager().install())
self.driver = webdriver.Chrome(service=service, options=chrome_options)
logger.info("TradingView driver setup completed")
return True
except Exception as e:
logger.error(f"Error setting up driver: {str(e)}")
return False
def navigate_to_tradingview(self, symbol="BTCUSDT", timeframe="1h"):
"""
رفتن به صفحه TradingView
"""
try:
url = f"https://www.tradingview.com/chart/?symbol={symbol}&interval={timeframe}"
self.driver.get(url)
time.sleep(5) # انتظار برای بارگذاری کامل صفحه
logger.info(f"Navigated to TradingView: {symbol} - {timeframe}")
return True
except Exception as e:
logger.error(f"Error navigating to TradingView: {str(e)}")
return False
def get_rsi_value(self):
"""
دریافت مقدار RSI (نمونه - باید با DOM واقعی TradingView تطبیق داده شود)
"""
try:
# این یک نمونه است - باید با ساختار واقعی TradingView تطبیق داده شود
# در عمل، باید المنت‌های مربوط به RSI را پیدا کرد
# شبیه‌سازی مقدار RSI
import random
rsi_value = random.uniform(20, 80)
# تعیین سیگنال بر اساس RSI
if rsi_value > 70:
signal = "فروش"
elif rsi_value < 30:
signal = "خرید"
else:
signal = "خنثی"
return {
"value": round(rsi_value, 2),
"signal": signal,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error getting RSI: {str(e)}")
return None
def get_macd_value(self):
"""
دریافت مقدار MACD
"""
try:
# شبیه‌سازی مقدار MACD
import random
macd_line = random.uniform(-0.5, 0.5)
signal_line = random.uniform(-0.5, 0.5)
histogram = macd_line - signal_line
# تعیین سیگنال
if macd_line > signal_line and histogram > 0:
signal = "خرید"
elif macd_line < signal_line and histogram < 0:
signal = "فروش"
else:
signal = "خنثی"
return {
"macd_line": round(macd_line, 4),
"signal_line": round(signal_line, 4),
"histogram": round(histogram, 4),
"signal": signal,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error getting MACD: {str(e)}")
return None
def get_ema_value(self):
"""
دریافت مقدار EMA
"""
try:
# شبیه‌سازی مقدار EMA
import random
current_price = random.uniform(40000, 50000)
ema_20 = random.uniform(39000, 51000)
# تعیین سیگنال
if current_price > ema_20:
signal = "خرید"
elif current_price < ema_20:
signal = "فروش"
else:
signal = "خنثی"
return {
"current_price": round(current_price, 2),
"ema_20": round(ema_20, 2),
"signal": signal,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error getting EMA: {str(e)}")
return None
def get_bollinger_bands(self):
"""
دریافت مقدار Bollinger Bands
"""
try:
# شبیه‌سازی Bollinger Bands
import random
current_price = random.uniform(40000, 50000)
upper_band = current_price + random.uniform(500, 2000)
lower_band = current_price - random.uniform(500, 2000)
middle_band = (upper_band + lower_band) / 2
# تعیین سیگنال
if current_price >= upper_band:
signal = "فروش"
elif current_price <= lower_band:
signal = "خرید"
else:
signal = "خنثی"
return {
"current_price": round(current_price, 2),
"upper_band": round(upper_band, 2),
"middle_band": round(middle_band, 2),
"lower_band": round(lower_band, 2),
"signal": signal,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error getting Bollinger Bands: {str(e)}")
return None
def get_stochastic_value(self):
"""
دریافت مقدار Stochastic
"""
try:
# شبیه‌سازی Stochastic
import random
k_percent = random.uniform(0, 100)
d_percent = random.uniform(0, 100)
# تعیین سیگنال
if k_percent > 80 and d_percent > 80:
signal = "فروش"
elif k_percent < 20 and d_percent < 20:
signal = "خرید"
else:
signal = "خنثی"
return {
"k_percent": round(k_percent, 2),
"d_percent": round(d_percent, 2),
"signal": signal,
"timestamp": datetime.now().isoformat()
}
except Exception as e:
logger.error(f"Error getting Stochastic: {str(e)}")
return None
def collect_all_indicators(self):
"""
جمع‌آوری تمام اندیکاتورها
"""
indicators = {}
try:
indicators["RSI"] = self.get_rsi_value()
indicators["MACD"] = self.get_macd_value()
indicators["EMA"] = self.get_ema_value()
indicators["Bollinger"] = self.get_bollinger_bands()
indicators["Stochastic"] = self.get_stochastic_value()
# حذف اندیکاتورهای None
indicators = {k: v for k, v in indicators.items() if v is not None}
self.indicators_data = indicators
return indicators
except Exception as e:
logger.error(f"Error collecting indicators: {str(e)}")
return {}
def check_signal_convergence(self):
"""
بررسی همگرایی سیگنال‌ها
"""
if not self.indicators_data:
return False, "No indicators data available"
signals = []
for indicator_name, data in self.indicators_data.items():
if data and "signal" in data:
signals.append(data["signal"])
if len(signals) < 5:
return False, f"Not enough indicators ({len(signals)}/5)"
# بررسی اینکه آیا همه سیگنال‌ها یکسان هستند
unique_signals = set(signals)
if len(unique_signals) == 1 and list(unique_signals)[0] != "خنثی":
signal_type = list(unique_signals)[0]
return True, f"All indicators show {signal_type} signal"
return False, f"Mixed signals: {dict(zip(self.indicators_data.keys(), signals))}"
def send_email_notification(self, message):
"""
ارسال اعلان ایمیل
"""
if not self.notification_settings["email"]["enabled"]:
return False, "Email notifications disabled"
try:
settings = self.notification_settings["email"]
# ایجاد پیام
msg = MimeMultipart()
msg['From'] = settings["username"]
msg['To'] = settings["recipient"]
msg['Subject'] = settings["subject"]
# محتوای ایمیل
body = f"""
TradingView Signal Alert
{message}
Indicators Data:
{json.dumps(self.indicators_data, indent=2, ensure_ascii=False)}
Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
"""
msg.attach(MimeText(body, 'plain', 'utf-8'))
# ارسال ایمیل
server = smtplib.SMTP(settings["smtp_server"], settings["smtp_port"])
server.starttls()
server.login(settings["username"], settings["password"])
text = msg.as_string()
server.sendmail(settings["username"], settings["recipient"], text)
server.quit()
logger.info("Email notification sent successfully")
return True, "Email sent successfully"
except Exception as e:
logger.error(f"Error sending email: {str(e)}")
return False, f"Email error: {str(e)}"
def send_webhook_notification(self, message):
"""
ارسال اعلان وب‌هوک
"""
if not self.notification_settings["webhook"]["enabled"]:
return False, "Webhook notifications disabled"
try:
settings = self.notification_settings["webhook"]
# آماده‌سازی payload
payload = {
"message": message,
"indicators": self.indicators_data,
"timestamp": datetime.now().isoformat()
}
# ادغام با payload سفارشی
if settings["payload"]:
payload.update(settings["payload"])
# ارسال درخواست
if settings["method"].upper() == "POST":
response = requests.post(
settings["url"],
json=payload,
headers={"Content-Type": "application/json"},
timeout=10
)
elif settings["method"].upper() == "GET":
response = requests.get(
settings["url"],
params=payload,
timeout=10
)
else:
return False, f"Unsupported method: {settings['method']}"
if response.status_code == 200:
logger.info("Webhook notification sent successfully")
return True, "Webhook sent successfully"
else:
return False, f"Webhook error: {response.status_code}"
except Exception as e:
logger.error(f"Error sending webhook: {str(e)}")
return False, f"Webhook error: {str(e)}"
def send_notifications(self, message):
"""
ارسال تمام اعلان‌ها
"""
results = []
# ارسال ایمیل
email_success, email_msg = self.send_email_notification(message)
results.append(f"Email: {email_msg}")
# ارسال وب‌هوک
webhook_success, webhook_msg = self.send_webhook_notification(message)
results.append(f"Webhook: {webhook_msg}")
return results
def monitoring_loop(self, symbol, timeframe, check_interval=60):
"""
حلقه اصلی نظارت
"""
logger.info(f"Starting monitoring for {symbol} - {timeframe}")
while self.is_monitoring:
try:
# جمع‌آوری اندیکاتورها
indicators = self.collect_all_indicators()
if indicators:
# بررسی همگرایی سیگنال‌ها
convergence, message = self.check_signal_convergence()
if convergence:
# ارسال اعلان
notification_message = f"TradingView Signal Alert for {symbol}: {message}"
results = self.send_notifications(notification_message)
logger.info(f"Signal convergence detected: {message}")
logger.info(f"Notification results: {results}")
# ذخیره آخرین سیگنال
self.last_signals[symbol] = {
"message": message,
"timestamp": datetime.now().isoformat(),
"indicators": indicators
}
# انتظار تا بررسی بعدی
time.sleep(check_interval)
except Exception as e:
logger.error(f"Error in monitoring loop: {str(e)}")
time.sleep(check_interval)
def start_monitoring(self, symbol="BTCUSDT", timeframe="1h", check_interval=60):
"""
شروع نظارت
"""
if self.is_monitoring:
return False, "Monitoring is already running"
try:
# راه‌اندازی درایور
if not self.setup_driver():
return False, "Failed to setup driver"
# رفتن به TradingView
if not self.navigate_to_tradingview(symbol, timeframe):
return False, "Failed to navigate to TradingView"
# شروع نظارت در thread جداگانه
self.is_monitoring = True
self.monitoring_thread = threading.Thread(
target=self.monitoring_loop,
args=(symbol, timeframe, check_interval)
)
self.monitoring_thread.daemon = True
self.monitoring_thread.start()
logger.info(f"Monitoring started for {symbol} - {timeframe}")
return True, f"Monitoring started for {symbol} - {timeframe}"
except Exception as e:
logger.error(f"Error starting monitoring: {str(e)}")
return False, f"Error starting monitoring: {str(e)}"
def stop_monitoring(self):
"""
توقف نظارت
"""
self.is_monitoring = False
if self.driver:
try:
self.driver.quit()
except:
pass
if self.monitoring_thread and self.monitoring_thread.is_alive():
self.monitoring_thread.join(timeout=5)
logger.info("Monitoring stopped")
return True, "Monitoring stopped"
def update_notification_settings(self, settings):
"""
به‌روزرسانی تنظیمات اعلان‌ها
"""
try:
self.notification_settings.update(settings)
logger.info("Notification settings updated")
return True, "Settings updated successfully"
except Exception as e:
logger.error(f"Error updating settings: {str(e)}")
return False, f"Error updating settings: {str(e)}"
def test_email_notification(self):
"""
تست ارسال ایمیل
"""
test_message = "This is a test email from TradingView Monitor"
return self.send_email_notification(test_message)
def test_webhook_notification(self):
"""
تست ارسال وب‌هوک
"""
test_message = "This is a test webhook from TradingView Monitor"
return self.send_webhook_notification(test_message)
def get_status(self):
"""
دریافت وضعیت فعلی سیستم
"""
return {
"is_monitoring": self.is_monitoring,
"last_check": datetime.now().isoformat(),
"indicators_count": len(self.indicators_data),
"last_signals": self.last_signals,
"email_enabled": self.notification_settings["email"]["enabled"],
"webhook_enabled": self.notification_settings["webhook"]["enabled"]
}
# تابع کمکی برای راه‌اندازی مانیتور TradingView در Streamlit
@st.cache_resource
def get_tradingview_monitor():
"""
دریافت نمونه مانیتور TradingView (با کش برای بهینه‌سازی)
"""
return TradingViewMonitor()
# کلاس مدیریت کرون‌جاب
class CronJobManager:
def __init__(self, monitor):
self.monitor = monitor
self.jobs = []
def add_monitoring_job(self, symbol, timeframe, check_interval):
"""
افزودن کار نظارت به کرون‌جاب
"""
try:
# پاک کردن کارهای قبلی
schedule.clear()
# افزودن کار جدید
schedule.every(check_interval).seconds.do(
self.monitor.collect_all_indicators
)
logger.info(f"Cron job added for {symbol} every {check_interval} seconds")
return True, "Cron job added successfully"
except Exception as e:
logger.error(f"Error adding cron job: {str(e)}")
return False, f"Error adding cron job: {str(e)}"
def run_pending_jobs(self):
"""
اجرای کارهای در انتظار
"""
schedule.run_pending()
def clear_all_jobs(self):
"""
پاک کردن تمام کارها
"""
schedule.clear()
logger.info("All cron jobs cleared")