markaz_arshy/server_comm.py
2025-08-12 14:36:24 +00:00

97 lines
No EOL
3.7 KiB
Python

# server_comm.py
#
# Deskripsi:
# Versi ini telah disempurnakan untuk mendukung semua tipe order:
# Market (Buy/Sell Entry), Stop (Buy/Sell Stop), dan Limit (Buy/Sell Limit).
from __future__ import annotations
import logging
import requests
from typing import Dict, Any
def send_signal_to_server(**payload: Any) -> str:
"""Mengirim sinyal trading ke server dan mengembalikan status keberhasilan."""
# Ekstrak URL dan secret_key, lalu hapus dari payload
server_url = payload.pop("server_url", None)
secret_key = payload.pop("secret_key", None)
if not server_url:
logging.error("server_url tidak ditemukan di payload. Sinyal tidak dikirim.")
return 'FAILED'
headers = {}
if secret_key:
headers['X-Secret-Key'] = secret_key
else:
logging.warning("secret_key tidak ditemukan di payload. Mengirim tanpa otorisasi.")
signal_json = payload.get("signal_json", {})
if not isinstance(signal_json, dict):
logging.error("Tipe data signal_json tidak valid (harus dictionary). Sinyal tidak dikirim.")
return 'FAILED'
order_type = payload.get("order_type", "WAIT")
symbol = payload.get("symbol", "UNKNOWN")
# Menentukan `signal_type` umum berdasarkan `order_type`
if "CANCEL" in order_type.upper() or "DELETE" in order_type.upper():
payload['signal'] = "CANCEL"
elif "BUY" in order_type.upper():
payload['signal'] = "BUY"
elif "SELL" in order_type.upper():
payload['signal'] = "SELL"
else:
payload['signal'] = "WAIT"
try:
response = requests.post(server_url, json=payload, headers=headers, timeout=10)
log_message = f"Sinyal {payload.get('signal', 'UNKNOWN')} untuk {symbol} dikirim."
if response.status_code == 200:
logging.info(f"{log_message} Status: BERHASIL.")
return 'SUCCESS'
elif 400 <= response.status_code < 500:
logging.error(f"{log_message} Status: DITOLAK. Respons: {response.text}")
return 'REJECTED'
else:
logging.error(f"{log_message} Status: GAGAL. Kode: {response.status_code}, Respons: {response.text}")
return 'FAILED'
except requests.exceptions.RequestException as e:
logging.error(f"❌ Error koneksi saat mengirim sinyal: {e}")
return 'FAILED'
def cancel_signal(signal_id: str, active_signals: Dict[str, Dict[str, any]], api_key: str, server_url: str, secret_key: str) -> None:
"""Membangun dan mengirim sinyal pembatalan untuk semua tipe order (Market, Limit, Stop)."""
if signal_id not in active_signals:
return
original = active_signals[signal_id]['signal_json']
symbol = original.get("Symbol")
entry_val = (original.get("BuyEntry") or original.get("SellEntry") or
original.get("BuyStop") or original.get("SellStop") or
original.get("BuyLimit") or original.get("SellLimit"))
if not symbol or not entry_val:
logging.error(f"Data tidak lengkap untuk membatalkan sinyal ID {signal_id}.")
return
cancel_json = {
"Symbol": symbol,
"DeleteLimit/Stop": entry_val,
"BuyEntry": "", "BuySL": "", "BuyTP": "", "SellEntry": "", "SellSL": "", "SellTP": "",
"BuyStop": "", "BuyStopSL": "", "BuyStopTP": "", "SellStop": "", "SellStopSL": "", "SellStopTP": "",
"BuyLimit": "", "BuyLimitSL": "", "BuyLimitTP": "", "SellLimit": "", "SellLimitSL": "", "SellLimitTP": "",
}
payload = {
"symbol": symbol,
"signal_json": cancel_json,
"api_key": api_key,
"server_url": server_url,
"secret_key": secret_key,
"order_type": "CANCEL_ORDER"
}
send_signal_to_server(**payload)
del active_signals[signal_id]