Pengujian Balik Keputusan Agen
Mensimulasikan strategi agen pada data historis untuk memvalidasi kinerja.
Pengujian Balik Keputusan Agen adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.
Mengapa Menguji Keputusan Agen dengan Data Historis?
Anda tidak dapat mengetahui apakah agen keuangan Anda menghasilkan rekomendasi yang baik tanpa mengujinya menggunakan data historis. Pengujian historis memutar ulang kondisi pasar masa lalu melalui logika keputusan agen dan mengukur bagaimana keputusan tersebut akan memberikan hasil.
Pengujian ini merupakan alat utama untuk memvalidasi kualitas strategi sebelum penerapan langsung.
Jebakan Bias Melihat ke Masa Depan
Bias melihat ke masa depan adalah kesalahan yang paling umum dan berbahaya dalam pengujian historis: menggunakan data masa depan untuk membuat keputusan yang seolah-olah dibuat di masa lalu. Contohnya, menggunakan harga penutupan hari itu untuk memutuskan apakah akan membeli saat pembukaan pada hari yang sama.
Setiap keputusan historis hanya boleh menggunakan data yang tersedia pada waktu keputusan yang disimulasikan.
import pandas as pd
import yfinance as yf
# WRONG — uses today's close to decide today's trade
def bad_signal(history: pd.DataFrame, date: str) -> str:
today_close = history.loc[date, 'Close'] # look-ahead!
if today_close > history['Close'].mean():
return 'BUY'
return 'HOLD'
# CORRECT — uses only data available BEFORE the decision date
def good_signal(history: pd.DataFrame, date: str) -> str:
past_data = history.loc[:date].iloc[:-1] # exclude today
if past_data.empty:
return 'HOLD'
today_open = history.loc[date, 'Open'] # open price known at market open
if today_open > past_data['Close'].mean():
return 'BUY'
return 'HOLD'Membangun Perulangan Pemutaran Ulang Historis
Ulangi proses untuk setiap tanggal historis. Pada setiap langkah, agen hanya melihat data yang tersedia hingga saat itu. Catat keputusannya, lalu lanjutkan ke tanggal berikutnya untuk mengamati hasilnya.
import yfinance as yf
import pandas as pd
def backtest_simple(ticker: str, start: str, end: str) -> list[dict]:
hist = yf.Ticker(ticker).history(start=start, end=end)
results = []
for i in range(20, len(hist)): # need 20 days of history for signals
window = hist.iloc[:i] # data available on day i
today = hist.iloc[i]
decision = good_signal(window, str(hist.index[i].date()))
results.append({
'date': str(hist.index[i].date()),
'decision': decision,
'open': float(today['Open']),
'close': float(today['Close']),
'next_day_return': None # filled in next iteration
})
return resultsMenyimulasikan Logika Agen pada Setiap Langkah
Untuk pengujian historis yang lebih realistis, simulasikan seluruh pemanggilan alat agen pada setiap tanggal — termasuk penyusunan perintah, pemanggilan LLM, dan penguraian keputusan. Dengan demikian, Anda menguji seluruh sistem, bukan hanya logika sinyal.
import openai, json
import yfinance as yf
client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')
def agent_decision_at_date(ticker: str, hist_up_to: pd.DataFrame) -> str:
recent = hist_up_to.tail(20)
closes = recent['Close'].tolist()
returns = [round((closes[i] - closes[i-1]) / closes[i-1], 4)
for i in range(1, len(closes))]
prompt = (
f'Ticker: {ticker}\n'
f'Last 20 closing prices: {closes}\n'
f'Daily returns: {returns}\n'
f'Based on this data, recommend: BUY, SELL, or HOLD.\n'
f'Return JSON: {{"action": "BUY/SELL/HOLD", "reason": "..."}}'
)
resp = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
response_format={'type': 'json_object'}
)
return json.loads(resp.choices[0].message.content).get('action', 'HOLD')Menghitung Tingkat Keberhasilan
Tingkat keberhasilan mengukur persentase keputusan BUY yang diikuti oleh imbal hasil positif pada hari berikutnya. Tingkat keberhasilan di atas 50% berarti agen memprediksi arah dengan benar lebih sering daripada kebetulan.
def compute_hit_rate(results: list[dict]) -> dict:
buy_decisions = [r for r in results if r['decision'] == 'BUY'
and r.get('next_day_return') is not None]
if not buy_decisions:
return {'hit_rate': None, 'sample_size': 0}
correct = sum(1 for r in buy_decisions if r['next_day_return'] > 0)
return {
'hit_rate': round(correct / len(buy_decisions), 4),
'sample_size': len(buy_decisions),
'correct': correct,
'interpretation': 'above_chance' if correct / len(buy_decisions) > 0.52 else 'at_or_below_chance'
}
if __name__ == '__main__':
results = [
{'decision': 'BUY', 'next_day_return': 0.012},
{'decision': 'BUY', 'next_day_return': -0.004},
{'decision': 'HOLD', 'next_day_return': None},
{'decision': 'BUY', 'next_day_return': 0.007},
]
print('Hit rate:', compute_hit_rate(results))
Menghitung Imbal Hasil Dibandingkan Tolok Ukur
Bandingkan imbal hasil strategi dengan tolok ukur beli dan simpan. Jika kinerja agen lebih rendah daripada sekadar menyimpan indeks, kompleksitasnya tidak dapat dibenarkan.
def compare_to_benchmark(results: list[dict], ticker: str, period: str = '1y') -> dict:
import yfinance as yf
# Strategy return: only invested on BUY days
buy_days = [r for r in results if r['decision'] == 'BUY'
and r.get('next_day_return') is not None]
strategy_return = sum(r['next_day_return'] for r in buy_days)
# Benchmark: buy-and-hold
hist = yf.Ticker(ticker).history(period=period)['Close']
bh_return = float((hist.iloc[-1] - hist.iloc[0]) / hist.iloc[0])
return {
'strategy_return_pct': round(strategy_return * 100, 2),
'benchmark_return_pct': round(bh_return * 100, 2),
'outperformed': strategy_return > bh_return,
'alpha_pct': round((strategy_return - bh_return) * 100, 2)
}Dampak Biaya Transaksi
Tanpa memperhitungkan biaya transaksi (komisi, selisih harga, dan selisih eksekusi), suatu strategi mungkin tampak menguntungkan, tetapi sebenarnya merugi dalam praktik. Bahkan 0,1% per transaksi dapat terakumulasi secara signifikan setelah banyak transaksi.
COMMISSION_PCT = 0.001 # 0.1% per trade (buy + sell)
SLIPPAGE_PCT = 0.0005 # 0.05% per trade
def returns_after_costs(decisions: list[dict]) -> dict:
total_return = 0.0
total_cost = 0.0
for d in decisions:
if d['decision'] == 'BUY' and d.get('next_day_return') is not None:
gross = d['next_day_return']
cost = COMMISSION_PCT + SLIPPAGE_PCT
net = gross - cost
total_return += net
total_cost += cost
return {
'gross_return_pct': round((total_return + total_cost) * 100, 2),
'net_return_pct': round(total_return * 100, 2),
'total_costs_pct': round(total_cost * 100, 2),
'num_trades': sum(1 for d in decisions if d['decision'] == 'BUY')
}
if __name__ == '__main__':
decisions = [
{'decision': 'BUY', 'next_day_return': 0.012},
{'decision': 'BUY', 'next_day_return': -0.004},
{'decision': 'HOLD', 'next_day_return': None},
]
print('Returns after trading costs:', returns_after_costs(decisions))
Validasi Maju-Bergulir
Pengoptimalan dalam sampel (melatih pada periode yang sama dengan periode pengujian) menyebabkan penyesuaian berlebihan. Validasi maju-bergulir menggunakan jendela pelatihan bergulir yang diikuti periode pengujian baru — sama seperti dalam penerapan nyata.
def walk_forward_test(ticker: str, total_years: int = 3,
train_months: int = 12, test_months: int = 3) -> list[dict]:
import yfinance as yf
from dateutil.relativedelta import relativedelta
from datetime import date
results = []
start = date(date.today().year - total_years, 1, 1)
end = date.today()
window_start = start
while True:
train_end = window_start + relativedelta(months=train_months)
test_end = train_end + relativedelta(months=test_months)
if test_end > end:
break
# In practice: train your signal on window_start->train_end
# then evaluate on train_end->test_end
results.append({
'train_period': f'{window_start} to {train_end}',
'test_period': f'{train_end} to {test_end}'
})
window_start += relativedelta(months=test_months)
return resultsLaporan Pengujian Historis
Rangkum hasil pengujian historis dalam laporan terstruktur: tingkat keberhasilan, total imbal hasil dibandingkan tolok ukur, alfa, rasio Sharpe, penurunan maksimum, jumlah transaksi, dan imbal hasil setelah biaya.
def backtest_report(ticker: str, results: list[dict]) -> dict:
hit = compute_hit_rate(results)
benchmark = compare_to_benchmark(results, ticker)
costs = returns_after_costs(results)
return {
'ticker': ticker,
'total_decisions': len(results),
'buy_signals': costs['num_trades'],
'hit_rate': hit.get('hit_rate'),
'strategy_return_gross': f'{costs["gross_return_pct"]}%',
'strategy_return_net': f'{costs["net_return_pct"]}%',
'benchmark_return': f'{benchmark["benchmark_return_pct"]}%',
'alpha': f'{benchmark["alpha_pct"]}%',
'outperformed_benchmark': benchmark['outperformed'],
'transaction_costs': f'{costs["total_costs_pct"]}%'
}Menafsirkan Hasil Pengujian Historis
Hasil pengujian historis yang baik tidak menjamin kinerja masa depan, tetapi hasil yang buruk dapat mengidentifikasi strategi yang seharusnya tidak diterapkan. Tanda peringatan utama: tingkat keberhasilan di bawah 50%, alfa negatif setelah biaya, rasio Sharpe di bawah 0,5, atau penurunan maksimum yang melebihi toleransi risiko Anda.
def interpret_backtest(report: dict) -> list[str]:
warnings = []
hit_rate = report.get('hit_rate')
if hit_rate and hit_rate < 0.50:
warnings.append(f'Hit rate {hit_rate:.1%} is below chance — strategy predicts direction poorly')
alpha_str = report.get('alpha', '0%')
alpha = float(alpha_str.replace('%', '')) / 100
if alpha < 0:
warnings.append(f'Negative alpha {alpha_str}: strategy underperforms buy-and-hold')
if not warnings:
return ['Backtest results look acceptable — proceed with paper trading before live deployment']
return warnings
if __name__ == '__main__':
report = {'hit_rate': 0.45, 'alpha': '-1.2%'}
for warning in interpret_backtest(report):
print('-', warning)
Simulasi Monte Carlo untuk Ketangguhan
Satu pengujian historis sensitif terhadap periode tertentu yang dipilih. Simulasi Monte Carlo mengacak urutan imbal hasil historis untuk menguji apakah kinerja tetap bertahan pada berbagai urutan, sehingga menunjukkan apakah strategi tersebut tangguh atau hanya beruntung.
import numpy as np
def monte_carlo_backtest(daily_returns: list[float],
simulations: int = 1000) -> dict:
returns_arr = np.array(daily_returns)
final_returns = []
for _ in range(simulations):
shuffled = np.random.choice(returns_arr, size=len(returns_arr), replace=True)
cumulative = float((1 + shuffled).prod() - 1)
final_returns.append(cumulative)
final_returns = sorted(final_returns)
return {
'median_return': round(float(np.median(final_returns)) * 100, 2),
'percentile_5': round(float(np.percentile(final_returns, 5)) * 100, 2),
'percentile_95': round(float(np.percentile(final_returns, 95)) * 100, 2),
'prob_positive': round(sum(1 for r in final_returns if r > 0) / simulations, 3)
}Apa yang dimaksud bias melihat ke masa depan dalam pengujian historis?
Bias melihat ke masa depan adalah cara paling umum untuk secara tidak sengaja melebih-lebihkan kinerja pengujian historis. Memahami definisi tepatnya mencegah Anda membangun pengujian historis yang keliru.
Ringkasan Keputusan Agen dalam Pengujian Historis
Pengujian historis yang baik memerlukan: menghindari bias melihat ke masa depan (keputusan hanya menggunakan data masa lalu), menyimulasikan logika agen yang realistis pada setiap langkah historis, mengukur tingkat keberhasilan dan alfa dibandingkan tolok ukur, memperhitungkan biaya transaksi, serta memvalidasi dengan pemisahan maju-bergulir untuk mendeteksi penyesuaian berlebihan.
Belajar AI Agents dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 60
- Pelajaran
- 239
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Pengujian Balik Keputusan Agen” gratis?
Ya — teks lengkap “Pengujian Balik Keputusan Agen” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Pengujian Balik Keputusan Agen”?
Mensimulasikan strategi agen pada data historis untuk memvalidasi kinerja. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Agents?
Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Pengujian Balik Keputusan Agen” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?
Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Integrasi API Data Pasar
- Alat Agen untuk Analisis Portofolio
- Batas Pengaman Risiko dan Kepatuhan
- Pengujian Balik Keputusan Agen