Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -26,25 +26,23 @@ def ema_manual(prices, span):
|
|
| 26 |
logging.debug(f"Memulai ema_manual untuk span={span}. Jumlah harga: {len(prices)}")
|
| 27 |
if len(prices) < span:
|
| 28 |
logging.warning(f"Tidak cukup data untuk menghitung EMA span {span}. Hanya {len(prices)} tersedia.")
|
| 29 |
-
return [np.nan] * len(prices)
|
| 30 |
|
| 31 |
ema = [np.nan] * len(prices)
|
| 32 |
alpha = 2 / (span + 1)
|
| 33 |
|
| 34 |
-
# Debugging pada loop EMA
|
| 35 |
try:
|
| 36 |
for i in range(len(prices)):
|
| 37 |
if i < span - 1:
|
| 38 |
ema[i] = np.nan
|
| 39 |
elif i == span - 1:
|
| 40 |
-
# Tambahkan logging di sini
|
| 41 |
logging.debug(f"Menghitung EMA awal untuk span={span} pada indeks {i}. Data: {prices[:span]}")
|
| 42 |
ema[i] = np.mean(prices[:span])
|
| 43 |
else:
|
| 44 |
ema[i] = alpha * prices[i] + (1 - alpha) * ema[i - 1]
|
| 45 |
except Exception as e:
|
| 46 |
logging.error(f"Error dalam loop ema_manual (span={span}, index={i}): {e}", exc_info=True)
|
| 47 |
-
raise
|
| 48 |
|
| 49 |
logging.debug(f"ema_manual selesai untuk span={span}.")
|
| 50 |
return ema
|
|
@@ -60,7 +58,7 @@ def get_dynamic_minmax():
|
|
| 60 |
close_min = df["Close"].min()
|
| 61 |
close_max = df["Close"].max()
|
| 62 |
logging.info(f"Min/Max Close: {close_min}/{close_max}")
|
| 63 |
-
return float(close_min), float(close_max)
|
| 64 |
|
| 65 |
def normalize_close(value, close_min, close_max):
|
| 66 |
if close_max == close_min:
|
|
@@ -69,14 +67,12 @@ def normalize_close(value, close_min, close_max):
|
|
| 69 |
return (value - close_min) / (close_max - close_min)
|
| 70 |
|
| 71 |
def analyze_trend(latest_row):
|
| 72 |
-
# Logging untuk memastikan data yang masuk valid
|
| 73 |
logging.debug(f"Menganalisis tren untuk data terbaru: {latest_row.to_dict()}")
|
| 74 |
|
| 75 |
ema20 = latest_row["EMA20"]
|
| 76 |
ema50 = latest_row["EMA50"]
|
| 77 |
close = latest_row["close"]
|
| 78 |
|
| 79 |
-
# ... (sisa fungsi analyze_trend tidak berubah)
|
| 80 |
if ema20 > ema50:
|
| 81 |
trend = "bullish"
|
| 82 |
elif ema20 < ema50:
|
|
@@ -84,7 +80,6 @@ def analyze_trend(latest_row):
|
|
| 84 |
else:
|
| 85 |
trend = "neutral"
|
| 86 |
|
| 87 |
-
# Pastikan ema50 tidak nol sebelum pembagian
|
| 88 |
if ema50 == 0:
|
| 89 |
logging.error("EMA50 adalah nol, tidak dapat menghitung gap persen.")
|
| 90 |
diff = 0
|
|
@@ -114,7 +109,7 @@ def analyze_trend(latest_row):
|
|
| 114 |
}
|
| 115 |
|
| 116 |
@app.post("/analyze")
|
| 117 |
-
def analyze_ema_endpoint(input_data: DateRange):
|
| 118 |
try:
|
| 119 |
logging.info(f"Menerima permintaan /analyze dengan start_date={input_data.start_date}, end_date={input_data.end_date}")
|
| 120 |
start_date = pd.to_datetime(input_data.start_date)
|
|
@@ -133,15 +128,15 @@ def analyze_ema_endpoint(input_data: DateRange): # Ganti nama fungsi agar tidak
|
|
| 133 |
logging.debug(f"Jumlah baris setelah download dan rename: {len(df)}")
|
| 134 |
|
| 135 |
if len(df) < 50:
|
| 136 |
-
# Perhatikan pesan error di sini, ini akan muncul di log, bukan di 'message'
|
| 137 |
logging.error(f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50.")
|
| 138 |
return {"status": "error", "message": f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50."}
|
| 139 |
|
| 140 |
-
# Logging sebelum memanggil ema_manual
|
| 141 |
logging.debug(f"Memanggil ema_manual untuk EMA20 dengan {len(df)} data.")
|
| 142 |
-
|
|
|
|
| 143 |
logging.debug(f"Memanggil ema_manual untuk EMA50 dengan {len(df)} data.")
|
| 144 |
-
|
|
|
|
| 145 |
|
| 146 |
df = df.dropna().reset_index(drop=True)
|
| 147 |
logging.debug(f"Jumlah baris setelah dropna: {len(df)}")
|
|
@@ -169,12 +164,11 @@ def analyze_ema_endpoint(input_data: DateRange): # Ganti nama fungsi agar tidak
|
|
| 169 |
}
|
| 170 |
|
| 171 |
except Exception as e:
|
| 172 |
-
# PENTING: Periksa output log server Anda untuk ini!
|
| 173 |
logging.error(f"Error TERTANGKAP di endpoint /analyze_ema_endpoint: {e}", exc_info=True)
|
| 174 |
return {"status": "error", "message": str(e)}
|
| 175 |
|
| 176 |
@app.post("/summary")
|
| 177 |
-
def ema_summary_endpoint(input_data: DateRange):
|
| 178 |
try:
|
| 179 |
logging.info(f"Menerima permintaan /summary dengan start_date={input_data.start_date}, end_date={input_data.end_date}")
|
| 180 |
start_date = pd.to_datetime(input_data.start_date)
|
|
@@ -196,8 +190,10 @@ def ema_summary_endpoint(input_data: DateRange): # Ganti nama fungsi
|
|
| 196 |
return {"status": "error", "message": f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50."}
|
| 197 |
|
| 198 |
logging.debug(f"Memanggil ema_manual untuk EMA20 dengan {len(df)} data.")
|
|
|
|
| 199 |
df["EMA20"] = ema_manual(df["close"].tolist(), 20)
|
| 200 |
logging.debug(f"Memanggil ema_manual untuk EMA50 dengan {len(df)} data.")
|
|
|
|
| 201 |
df["EMA50"] = ema_manual(df["close"].tolist(), 50)
|
| 202 |
df = df.dropna().reset_index(drop=True)
|
| 203 |
logging.debug(f"Jumlah baris setelah dropna: {len(df)}")
|
|
|
|
| 26 |
logging.debug(f"Memulai ema_manual untuk span={span}. Jumlah harga: {len(prices)}")
|
| 27 |
if len(prices) < span:
|
| 28 |
logging.warning(f"Tidak cukup data untuk menghitung EMA span {span}. Hanya {len(prices)} tersedia.")
|
| 29 |
+
return [np.nan] * len(prices)
|
| 30 |
|
| 31 |
ema = [np.nan] * len(prices)
|
| 32 |
alpha = 2 / (span + 1)
|
| 33 |
|
|
|
|
| 34 |
try:
|
| 35 |
for i in range(len(prices)):
|
| 36 |
if i < span - 1:
|
| 37 |
ema[i] = np.nan
|
| 38 |
elif i == span - 1:
|
|
|
|
| 39 |
logging.debug(f"Menghitung EMA awal untuk span={span} pada indeks {i}. Data: {prices[:span]}")
|
| 40 |
ema[i] = np.mean(prices[:span])
|
| 41 |
else:
|
| 42 |
ema[i] = alpha * prices[i] + (1 - alpha) * ema[i - 1]
|
| 43 |
except Exception as e:
|
| 44 |
logging.error(f"Error dalam loop ema_manual (span={span}, index={i}): {e}", exc_info=True)
|
| 45 |
+
raise
|
| 46 |
|
| 47 |
logging.debug(f"ema_manual selesai untuk span={span}.")
|
| 48 |
return ema
|
|
|
|
| 58 |
close_min = df["Close"].min()
|
| 59 |
close_max = df["Close"].max()
|
| 60 |
logging.info(f"Min/Max Close: {close_min}/{close_max}")
|
| 61 |
+
return float(close_min), float(close_max)
|
| 62 |
|
| 63 |
def normalize_close(value, close_min, close_max):
|
| 64 |
if close_max == close_min:
|
|
|
|
| 67 |
return (value - close_min) / (close_max - close_min)
|
| 68 |
|
| 69 |
def analyze_trend(latest_row):
|
|
|
|
| 70 |
logging.debug(f"Menganalisis tren untuk data terbaru: {latest_row.to_dict()}")
|
| 71 |
|
| 72 |
ema20 = latest_row["EMA20"]
|
| 73 |
ema50 = latest_row["EMA50"]
|
| 74 |
close = latest_row["close"]
|
| 75 |
|
|
|
|
| 76 |
if ema20 > ema50:
|
| 77 |
trend = "bullish"
|
| 78 |
elif ema20 < ema50:
|
|
|
|
| 80 |
else:
|
| 81 |
trend = "neutral"
|
| 82 |
|
|
|
|
| 83 |
if ema50 == 0:
|
| 84 |
logging.error("EMA50 adalah nol, tidak dapat menghitung gap persen.")
|
| 85 |
diff = 0
|
|
|
|
| 109 |
}
|
| 110 |
|
| 111 |
@app.post("/analyze")
|
| 112 |
+
def analyze_ema_endpoint(input_data: DateRange):
|
| 113 |
try:
|
| 114 |
logging.info(f"Menerima permintaan /analyze dengan start_date={input_data.start_date}, end_date={input_data.end_date}")
|
| 115 |
start_date = pd.to_datetime(input_data.start_date)
|
|
|
|
| 128 |
logging.debug(f"Jumlah baris setelah download dan rename: {len(df)}")
|
| 129 |
|
| 130 |
if len(df) < 50:
|
|
|
|
| 131 |
logging.error(f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50.")
|
| 132 |
return {"status": "error", "message": f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50."}
|
| 133 |
|
|
|
|
| 134 |
logging.debug(f"Memanggil ema_manual untuk EMA20 dengan {len(df)} data.")
|
| 135 |
+
# BARIS INI YANG DIPERBAIKI:
|
| 136 |
+
df["EMA20"] = ema_manual(df["close"].tolist(), 20)
|
| 137 |
logging.debug(f"Memanggil ema_manual untuk EMA50 dengan {len(df)} data.")
|
| 138 |
+
# BARIS INI YANG DIPERBAIKI:
|
| 139 |
+
df["EMA50"] = ema_manual(df["close"].tolist(), 50)
|
| 140 |
|
| 141 |
df = df.dropna().reset_index(drop=True)
|
| 142 |
logging.debug(f"Jumlah baris setelah dropna: {len(df)}")
|
|
|
|
| 164 |
}
|
| 165 |
|
| 166 |
except Exception as e:
|
|
|
|
| 167 |
logging.error(f"Error TERTANGKAP di endpoint /analyze_ema_endpoint: {e}", exc_info=True)
|
| 168 |
return {"status": "error", "message": str(e)}
|
| 169 |
|
| 170 |
@app.post("/summary")
|
| 171 |
+
def ema_summary_endpoint(input_data: DateRange):
|
| 172 |
try:
|
| 173 |
logging.info(f"Menerima permintaan /summary dengan start_date={input_data.start_date}, end_date={input_data.end_date}")
|
| 174 |
start_date = pd.to_datetime(input_data.start_date)
|
|
|
|
| 190 |
return {"status": "error", "message": f"Data terlalu sedikit ({len(df)} hari). Butuh minimal 50 hari untuk EMA50."}
|
| 191 |
|
| 192 |
logging.debug(f"Memanggil ema_manual untuk EMA20 dengan {len(df)} data.")
|
| 193 |
+
# BARIS INI YANG DIPERBAIKI:
|
| 194 |
df["EMA20"] = ema_manual(df["close"].tolist(), 20)
|
| 195 |
logging.debug(f"Memanggil ema_manual untuk EMA50 dengan {len(df)} data.")
|
| 196 |
+
# BARIS INI YANG DIPERBAIKI:
|
| 197 |
df["EMA50"] = ema_manual(df["close"].tolist(), 50)
|
| 198 |
df = df.dropna().reset_index(drop=True)
|
| 199 |
logging.debug(f"Jumlah baris setelah dropna: {len(df)}")
|