mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-27 18:57:47 +00:00
109 lines
4.4 KiB
Python
109 lines
4.4 KiB
Python
# core/routes/api_bots_analysis.py
|
|
|
|
from flask import Blueprint, jsonify
|
|
from core.bots.manager import active_bots
|
|
from core.data.fetch import get_rates as get_rates_from_mt5
|
|
import pandas_ta as ta
|
|
import MetaTrader5 as mt5
|
|
import pandas as pd
|
|
|
|
api_bots_analysis = Blueprint('api_bots_analysis', __name__)
|
|
|
|
@api_bots_analysis.route('/api/bots/<int:bot_id>/analysis')
|
|
def get_bot_analysis(bot_id):
|
|
bot_obj = active_bots.get(bot_id)
|
|
if not bot_obj:
|
|
return jsonify({'error': 'Objek bot tidak ditemukan di memori'}), 404
|
|
|
|
strategy = bot_obj.strategy
|
|
symbol = bot_obj.market.replace('/', '')
|
|
response_data = {}
|
|
|
|
try:
|
|
# --- LOGIKA DINAMIS BERDASARKAN STRATEGI ---
|
|
|
|
if strategy == 'MA_CROSSOVER':
|
|
df = get_rates_from_mt5(symbol, bot_obj.mt5_timeframe, 52)
|
|
if df is None or len(df) < 51: return jsonify({'error': 'Data tidak cukup'}), 400
|
|
|
|
df["ma_fast"] = ta.sma(df["close"], length=20)
|
|
df["ma_slow"] = ta.sma(df["close"], length=50)
|
|
df.dropna(inplace=True)
|
|
if df.empty: return jsonify({'error': 'Indikator belum matang'}), 400
|
|
|
|
last = df.iloc[-1]
|
|
signal = "BULLISH (Beli)" if last['ma_fast'] > last['ma_slow'] else "BEARISH (Jual)"
|
|
|
|
response_data = {
|
|
"price": last['close'],
|
|
"ma_fast": last['ma_fast'],
|
|
"ma_slow": last['ma_slow'],
|
|
"signal": signal
|
|
}
|
|
|
|
elif strategy == 'RSI_BREAKOUT':
|
|
df = get_rates_from_mt5(symbol, bot_obj.mt5_timeframe, 15)
|
|
if df is None or len(df) < 15: return jsonify({'error': 'Data tidak cukup'}), 400
|
|
|
|
df["rsi"] = ta.rsi(df["close"], length=14)
|
|
df.dropna(inplace=True)
|
|
if df.empty: return jsonify({'error': 'Indikator belum matang'}), 400
|
|
|
|
last = df.iloc[-1]
|
|
signal = "NETRAL"
|
|
if last['rsi'] > 70: signal = "OVERBOUGHT (Jual)"
|
|
elif last['rsi'] < 30: signal = "OVERSOLD (Beli)"
|
|
|
|
response_data = {
|
|
"price": last['close'],
|
|
"rsi": last['rsi'],
|
|
"signal": signal
|
|
}
|
|
|
|
elif strategy in ['MERCY_EDGE', 'FULL_MERCY']:
|
|
df_d1 = get_rates_from_mt5(symbol, mt5.TIMEFRAME_D1, 200)
|
|
df_h1 = get_rates_from_mt5(symbol, bot_obj.mt5_timeframe, 100)
|
|
if df_d1 is None or df_h1 is None or len(df_d1) < 50 or len(df_h1) < 30:
|
|
return jsonify({'error': 'Data tidak cukup'}), 400
|
|
|
|
df_d1.ta.macd(append=True)
|
|
df_h1.ta.macd(append=True)
|
|
df_h1.ta.stoch(append=True)
|
|
df_d1.dropna(inplace=True)
|
|
df_h1.dropna(inplace=True)
|
|
if df_d1.empty or df_h1.empty: return jsonify({'error': 'Indikator belum matang'}), 400
|
|
|
|
last_d1 = df_d1.iloc[-1]
|
|
last_h1 = df_h1.iloc[-1]
|
|
|
|
signal = "TAHAN"
|
|
if last_d1['MACDh_12_26_9'] > 0 and last_h1['MACDh_12_26_9'] > 0: signal = "BULLISH (Beli)"
|
|
elif last_d1['MACDh_12_26_9'] < 0 and last_h1['MACDh_12_26_9'] < 0: signal = "BEARISH (Jual)"
|
|
|
|
# ** PERBAIKAN KUNCI DI SINI: Samakan nama kunci dengan yang diharapkan JavaScript **
|
|
response_data = {
|
|
"price": last_h1['close'],
|
|
"D1_MACDh": last_d1['MACDh_12_26_9'],
|
|
"H1_MACDh": last_h1['MACDh_12_26_9'],
|
|
"H1_STOCHk": last_h1['STOCHk_14_3_3'],
|
|
"H1_STOCHd": last_h1['STOCHd_14_3_3'],
|
|
"signal": signal
|
|
}
|
|
|
|
else:
|
|
last_price_df = get_rates_from_mt5(symbol, bot_obj.mt5_timeframe, 1)
|
|
if last_price_df is not None and not last_price_df.empty:
|
|
response_data = {
|
|
"price": last_price_df.iloc[-1]['close'],
|
|
"signal": "TAHAN",
|
|
"info": f"UI Analisis untuk strategi '{strategy}' belum diimplementasikan."
|
|
}
|
|
else:
|
|
return jsonify({'error': 'Gagal mengambil harga terakhir'}), 400
|
|
|
|
return jsonify(response_data)
|
|
|
|
except Exception as e:
|
|
print(f"CRITICAL ERROR in get_bot_analysis for bot {bot_id} ({strategy}): {e}")
|
|
# Kirim error 500 yang jelas jika terjadi crash
|
|
return jsonify({'error': 'Terjadi kesalahan internal di server saat melakukan analisis.'}), 500 |