mirror of
https://github.com/chrisnov-it/quantumbotx.git
synced 2026-07-28 03:07:53 +00:00
7b74743d58
Refactor the JavaScript code to use a single modal for both forex and stock profiles. Update error handling to display server error messages. Remove unused app.py and fetch.py files. Adjust various routes and strategies for consistency.
117 lines
4.4 KiB
Python
117 lines
4.4 KiB
Python
# backtester.py
|
|
import pandas as pd
|
|
import pandas_ta as ta
|
|
import matplotlib.pyplot as plt
|
|
|
|
def get_profit_multiplier(symbol, lot_size=0.01):
|
|
"""
|
|
Mengembalikan multiplier yang benar untuk perhitungan profit berdasarkan
|
|
simbol, kelas aset, dan ukuran lot.
|
|
"""
|
|
# 1. Untuk Indeks Saham (seperti US500, NAS100, SPX500m, dll.)
|
|
# Pergerakan 1 poin = profit $0.01 untuk 0.01 lot.
|
|
if "500" in symbol or "100" in symbol or "30" in symbol:
|
|
return 1 * lot_size
|
|
|
|
# 2. Untuk Emas (XAUUSD)
|
|
# Pergerakan $1 = profit $1 untuk 0.01 lot.
|
|
elif "XAU" in symbol:
|
|
return 100 * lot_size
|
|
|
|
# 3. Untuk Pasangan Mata Uang Forex (seperti EURUSD, USDJPY)
|
|
# Pergerakan 1 pip = profit ~$0.10 untuk 0.01 lot.
|
|
# Nilai 100000 adalah standar industri untuk 1 lot.
|
|
else:
|
|
# Periksa apakah ini pasangan JPY, karena nilainya berbeda
|
|
if "JPY" in symbol:
|
|
return 1000 * lot_size # Untuk pasangan JPY, 1 pip adalah 0.01
|
|
else:
|
|
return 100000 * lot_size # Untuk pasangan non-JPY, 1 pip adalah 0.0001
|
|
|
|
def run_backtest(data_path, symbol, initial_balance=10000):
|
|
"""Fungsi utama untuk menjalankan simulasi backtesting."""
|
|
|
|
print(f"Memulai backtest MA_CROSSOVER untuk simbol: {symbol}")
|
|
# Kode baru yang disarankan
|
|
LOT_SIZE = 0.01 # Definisikan ukuran lot di satu tempat
|
|
multiplier = get_profit_multiplier(symbol, LOT_SIZE)
|
|
print(f"Multiplier profit yang digunakan: {multiplier}")
|
|
|
|
# 1. Muat dan siapkan data historis
|
|
df = pd.read_csv(data_path, parse_dates=['time'])
|
|
|
|
# --- Parameter Strategi ---
|
|
FAST_MA = 20
|
|
SLOW_MA = 50
|
|
|
|
# Hitung indikator
|
|
df.ta.sma(length=FAST_MA, append=True)
|
|
df.ta.sma(length=SLOW_MA, append=True)
|
|
|
|
fast_ma_col = f'SMA_{FAST_MA}'
|
|
slow_ma_col = f'SMA_{SLOW_MA}'
|
|
|
|
# 2. Siapkan variabel untuk simulasi
|
|
balance = initial_balance
|
|
position = None
|
|
trades = []
|
|
equity_curve = []
|
|
|
|
print("Memulai Loop Backtest...")
|
|
# 3. Loop utama
|
|
for i in range(1, len(df)):
|
|
current_row = df.iloc[i]
|
|
prev_row = df.iloc[i - 1]
|
|
|
|
# --- Simulasi Logika Exit ---
|
|
if position:
|
|
# Sinyal keluar untuk BUY adalah Death Cross
|
|
if position['type'] == 'BUY' and prev_row[fast_ma_col] > prev_row[slow_ma_col] and current_row[fast_ma_col] < current_row[slow_ma_col]:
|
|
# --- PERBAIKAN DI SINI ---
|
|
profit = (current_row['close'] - position['entry_price']) * multiplier
|
|
balance += profit
|
|
trades.append({'profit': profit})
|
|
position = None
|
|
|
|
# Sinyal keluar untuk SELL adalah Golden Cross
|
|
elif position['type'] == 'SELL' and prev_row[fast_ma_col] < prev_row[slow_ma_col] and current_row[fast_ma_col] > current_row[slow_ma_col]:
|
|
# --- PERBAIKAN DI SINI ---
|
|
profit = (position['entry_price'] - current_row['close']) * multiplier
|
|
balance += profit
|
|
trades.append({'profit': profit})
|
|
position = None
|
|
|
|
# --- Simulasi Logika Entry ---
|
|
if not position:
|
|
# Golden Cross (Sinyal BELI)
|
|
if prev_row[fast_ma_col] <= prev_row[slow_ma_col] and current_row[fast_ma_col] > current_row[slow_ma_col]:
|
|
position = {'type': 'BUY', 'entry_price': current_row['close']}
|
|
# Death Cross (Sinyal JUAL)
|
|
elif prev_row[fast_ma_col] >= prev_row[slow_ma_col] and current_row[fast_ma_col] < current_row[slow_ma_col]:
|
|
position = {'type': 'SELL', 'entry_price': current_row['close']}
|
|
|
|
equity_curve.append(balance)
|
|
|
|
# 4. Analisis Hasil
|
|
print("\n--- Backtest Selesai ---")
|
|
print(f"Balance Awal: ${initial_balance:.2f}")
|
|
print(f"Balance Akhir: ${balance:.2f}")
|
|
total_profit = balance - initial_balance
|
|
print(f"Total Profit/Loss: ${total_profit:.2f} ({total_profit/initial_balance*100:.2f}%)")
|
|
print(f"Total Trades: {len(trades)}")
|
|
|
|
# Tampilkan Grafik Equity
|
|
plt.figure(figsize=(12, 6))
|
|
plt.plot(df['time'].iloc[1:], equity_curve)
|
|
plt.title(f'Equity Curve - Strategi MA_CROSSOVER on {symbol}')
|
|
plt.xlabel('Tanggal')
|
|
plt.ylabel('Balance ($)')
|
|
plt.grid(True)
|
|
plt.show()
|
|
|
|
# --- Jalankan Backtest ---
|
|
if __name__ == '__main__':
|
|
symbol_to_test = "GBPJPY"
|
|
file_name = "lab/XAUUSD_16385_data.csv"
|
|
|
|
run_backtest(file_name, symbol=symbol_to_test) |