Bot & Automation

Treding Forex Ai

/root/hermes-projects/Treding Forex Ai

dist/src/services/safetyFilter.js text
"use strict";
/**
 * Safety Filter — dijalankan sebelum setiap scan auto-trading.
 *
 * Filter ini memastikan bot tidak entry saat kondisi pasar berbahaya:
 * - Spread terlalu lebar (volatilitas ekstrem)
 * - Market sedang dalam rollover window (XAUUSD: 23:00–01:00 UTC)
 * - Daily loss sudah melebihi batas maksimum
 * - Sudah ada open posisi untuk simbol yang sama
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.SafetyFilter = void 0;
class SafetyFilter {
    config;
    constructor(config) {
        this.config = config;
    }
    updateConfig(newConfig) {
        Object.assign(this.config, newConfig);
    }
    /**
     * Cek semua kondisi keamanan.
     * @param symbolCode Kode simbol yang akan di-scan
     * @param currentSpreadPips Spread saat ini dalam pips
     * @param todayLossAmount Total kerugian hari ini (positif = rugi)
     * @param openPositionCount Jumlah posisi terbuka untuk simbol ini
     */
    check(symbolCode, currentSpreadPips, todayLossAmount, openPositionCount) {
        const reasons = [];
        // 1. Spread check
        if (currentSpreadPips > this.config.maxSpreadPips) {
            reasons.push(`Spread ${currentSpreadPips.toFixed(1)} pips melebihi batas ${this.config.maxSpreadPips} pips — pasar terlalu volatile.`);
        }
        // 2. Rollover window check (berlaku untuk semua simbol forex/gold)
        if (this.config.skipRolloverWindow && isRolloverWindow()) {
            reasons.push(`Market sedang dalam rollover window (23:00–01:00 UTC) — skip entry ${symbolCode}.`);
        }
        // 3. Daily loss limit check (hanya aktif jika maxDailyLossAmount > 0)
        if (this.config.maxDailyLossAmount > 0 && todayLossAmount >= this.config.maxDailyLossAmount) {
            reasons.push(`Daily loss ${todayLossAmount.toFixed(2)} sudah mencapai batas ${this.config.maxDailyLossAmount.toFixed(2)} — trading dihentikan hari ini.`);
        }
        // 4. Open position limit untuk simbol ini (0 = tidak ada batas)
        const maxPos = this.config.maxOpenPositions;
        if (maxPos > 0 && openPositionCount >= maxPos) {
            reasons.push(`Sudah ada ${openPositionCount} posisi terbuka untuk ${symbolCode} (maks ${maxPos}) — skip entry baru.`);
        }
        return {
            safe: reasons.length === 0,
            reasons
        };
    }
    /**
     * Estimasi spread saat ini dari data candle terakhir (ATR-based).
     * Jika tidak ada data live, gunakan defaultSpreadPips dari symbol config.
     * @param atr Average True Range dari candle terakhir
     * @param pipSize Ukuran 1 pip untuk simbol ini
     * @param defaultSpreadPips Spread default jika ATR tidak tersedia
     */
    static estimateSpreadPips(atr, pipSize, defaultSpreadPips) {
        if (atr <= 0 || pipSize <= 0) {
            return defaultSpreadPips;
        }
        // ATR yang sangat tinggi biasanya terjadi saat spread melebar juga
        // Gunakan 5% dari ATR sebagai estimasi spread dalam pips
        const atrBasedEstimate = (atr * 0.05) / pipSize;
        return Math.max(atrBasedEstimate, defaultSpreadPips);
    }
}
exports.SafetyFilter = SafetyFilter;
/**
 * Cek apakah sekarang adalah rollover window XAUUSD/Forex.
 * Rollover terjadi antara 23:00–01:00 UTC setiap hari kerja.
 */
function isRolloverWindow() {
    const now = new Date();
    const hourUtc = now.getUTCHours();
    const minuteUtc = now.getUTCMinutes();
    const decimalHour = hourUtc + minuteUtc / 60;
    // 23:00 UTC hingga 01:00 UTC (melewati tengah malam)
    return decimalHour >= 23 || decimalHour < 1;
}