-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmarket_report.py
More file actions
171 lines (145 loc) · 5.57 KB
/
Copy pathmarket_report.py
File metadata and controls
171 lines (145 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"""
Market Report — דוח שוק מלא לטלגרם
שולח את כל הנכסים עם RSI + כיוון, כל 15 דקות
"""
import sys, asyncio, os, time
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
from pathlib import Path
from dotenv import load_dotenv
from datetime import datetime
import yfinance as yf
import pandas as pd
load_dotenv(Path.home() / "tv_webhook" / ".env")
TOKEN = os.getenv("TELEGRAM_TOKEN")
CHAT_ID = os.getenv("ALL_CHAT_ID", "1246833993")
ASSETS = {
# מדדים
"NAS100": {"symbol": "^NDX", "group": "Indices"},
"S&P500": {"symbol": "^GSPC", "group": "Indices"},
"DOW": {"symbol": "^DJI", "group": "Indices"},
"DAX": {"symbol": "^GDAXI", "group": "Indices"},
"Nikkei": {"symbol": "^N225", "group": "Indices"},
# סחורות
"XAUUSD": {"symbol": "GC=F", "group": "Commodities"},
"XAGUSD": {"symbol": "SI=F", "group": "Commodities"},
"WTI": {"symbol": "CL=F", "group": "Commodities"},
"Brent": {"symbol": "BZ=F", "group": "Commodities"},
"NatGas": {"symbol": "NG=F", "group": "Commodities"},
# פורקס
"EURUSD": {"symbol": "EURUSD=X", "group": "Forex"},
"GBPUSD": {"symbol": "GBPUSD=X", "group": "Forex"},
"USDJPY": {"symbol": "JPY=X", "group": "Forex"},
"AUDUSD": {"symbol": "AUDUSD=X", "group": "Forex"},
"USDCAD": {"symbol": "CAD=X", "group": "Forex"},
"USDCHF": {"symbol": "CHF=X", "group": "Forex"},
"EURGBP": {"symbol": "EURGBP=X", "group": "Forex"},
# קריפטו
"BTCUSD": {"symbol": "BTC-USD", "group": "Crypto"},
"ETHUSD": {"symbol": "ETH-USD", "group": "Crypto"},
}
INTERVAL = 15 * 60 # כל 15 דקות
GROUP_EMOJI = {
"Indices": "📊",
"Commodities": "🛢",
"Forex": "💱",
"Crypto": "🔶",
}
def compute_rsi(series: pd.Series, period: int = 14) -> float:
delta = series.diff()
gain = delta.clip(lower=0).rolling(period).mean()
loss = (-delta.clip(upper=0)).rolling(period).mean()
rs = gain / loss.replace(0, 1e-9)
return round(100 - 100 / (1 + rs.iloc[-1]), 1)
def scan_asset(name: str, info: dict) -> dict:
try:
h = yf.Ticker(info["symbol"]).history(period="3d", interval="15m")
if len(h) < 20:
return {"name": name, "group": info["group"], "error": True}
close = h["Close"]
price = round(close.iloc[-1], 4)
rsi = compute_rsi(close)
ma20 = round(close.rolling(20).mean().iloc[-1], 4)
if rsi < 30:
signal = "LONG"
label = "Oversold"
elif rsi < 35:
signal = "LONG"
label = "Weak Long"
elif rsi > 70:
signal = "SHORT"
label = "Overbought"
elif rsi > 65:
signal = "SHORT"
label = "Weak Short"
elif price > ma20 and 48 < rsi < 65:
signal = "LONG"
label = "Momentum"
elif price < ma20 and 35 < rsi < 52:
signal = "SHORT"
label = "Neg. Momentum"
else:
signal = "WAIT"
label = "Neutral"
return {
"name": name,
"group": info["group"],
"price": price,
"rsi": rsi,
"signal": signal,
"label": label,
"error": False,
}
except Exception:
return {"name": name, "group": info["group"], "error": True}
def signal_icon(signal: str) -> str:
return {"LONG": "🟢", "SHORT": "🔴", "WAIT": "⚪"}.get(signal, "⚪")
async def send_report(results: list):
import telegram
bot = telegram.Bot(token=TOKEN)
now = datetime.now().strftime("%d/%m/%Y %H:%M")
# ספירת סיגנלים
longs = [r for r in results if r.get("signal") == "LONG"]
shorts = [r for r in results if r.get("signal") == "SHORT"]
waits = [r for r in results if r.get("signal") == "WAIT"]
msg = f"*דוח שוק — {now}*\n"
msg += f"🟢 LONG: {len(longs)} | 🔴 SHORT: {len(shorts)} | ⚪ ממתין: {len(waits)}\n"
msg += "─" * 28 + "\n\n"
# קיבוץ לפי קבוצה
groups = {}
for r in results:
g = r["group"]
groups.setdefault(g, []).append(r)
for group, items in groups.items():
emoji = GROUP_EMOJI.get(group, "•")
msg += f"{emoji} *{group}*\n"
for r in items:
if r.get("error"):
msg += f" • {r['name']:8} — שגיאה\n"
continue
icon = signal_icon(r["signal"])
msg += f" {icon} {r['name']:8} | {r['signal']:5} | RSI {r['rsi']:4} | {r['label']}\n"
msg += f" מחיר: {r['price']}\n"
msg += "\n"
msg += "_DYOR — Not financial advice_"
await bot.send_message(chat_id=CHAT_ID, text=msg, parse_mode="Markdown")
print(f"[{now}] דוח נשלח — {len(results)} נכסים")
def run_once():
now = datetime.now().strftime("%H:%M")
print(f"\n[{now}] סורק {len(ASSETS)} נכסים...")
results = []
for name, info in ASSETS.items():
r = scan_asset(name, info)
results.append(r)
if r.get("error"):
print(f" {name:10} — שגיאה")
else:
print(f" {r['signal']:5} {name:10} | RSI {r['rsi']}")
asyncio.run(send_report(results))
if __name__ == "__main__":
print("=" * 50)
print(f"Market Report — {len(ASSETS)} נכסים")
print(f"שולח כל {INTERVAL // 60} דקות | Chat: {CHAT_ID}")
print("=" * 50)
while True:
run_once()
time.sleep(INTERVAL)