Olay Güdümlü Bir Geriye Dönük Test: ATR Stopları, Pozisyon Büyüklüğü ve R-Katlarıyla Bir İşlem Listesi İçeren Döngü Motoru
Pozisyonları ATR riskine göre boyutlandıran, fiyat boşlukları dahil stoplara uyan ve her işlemi R-katı olarak kaydeden, çubuk çubuk ilerleyen bir Python geriye dönük test döngüsü oluşturun.
Neler öğreneceksiniz
- Vektörleştirilmiş bir geriye dönük testin stopları, kısmi gerçekleşmeleri veya riske dayalı pozisyon büyüklüğünü neden modelleyemediği ve bir döngü motoruna ne zaman ihtiyaç duyulduğu.
- Olay güdümlü bir motorun çubuktan çubuğa taşıması gereken durum: nakit, pozisyon, giriş fiyatı, stop seviyesi ve açık işlem.
- Her pozisyonun hesap riski ve ATR'den nasıl boyutlandırılacağı ve sonucun bir R-katı olarak nasıl kaydedileceği.
- Stopun üzerinden atlayan fiyat boşluklarının kodda nasıl dürüstçe ele alınacağı.
Açıklama
7. dersteki vektörleştirilmiş geriye dönük test, her çubuğun pozisyonunu tüm seriden tek seferde hesaplar. Hızlıdır, ancak izlenen yola bağlı kuralları ifade edemez: girişin 2 ATR altındaki bir stop nereden girdiğinize bağlıdır ve pozisyon büyüklüğü o andaki hesap değerine bağlıdır. Olay güdümlü bir geriye dönük test çubukları tek tek dolaşır, yalnızca o çubuğa kadar mevcut olan bilgiyi kullanır ve durumunu tam olarak bir trader'ın yapacağı gibi günceller.
Durum ve olayların sırası
Motor küçük bir değişken seti tutar: cash, position (hisse adedi, pozisyon yokken 0), entry, stop, risk_per_share ve bir trades listesi. Her çubukta kontrollerin sırası önemlidir; bir kez yazılmalı ve korunmalıdır:
- Önce çıkışlar. Açık bir pozisyon varsa ve bugünün en düşüğü stopta veya altındaysa çıkış yapın. Gerçekleşme fiyatı stoptur; ancak açılış zaten stopun altındaysa (bir fiyat boşluğu), gerçekleşme fiyatı açılıştır. Planlanan 1R'lik bir kaybın 1.4R veya daha fazlasına dönüşebileceği yer burasıdır.
- İz süren stopları bugünün kapanışı ve ATR'si ile güncelleyin.
- Girişler en son ve yalnızca bir sonraki çubuğun açılışında yapılır, çünkü bugünün kapanışından hesaplanan bir sinyalle bugünün kapanışında işlem yapılamaz. Kodda bu şu anlama gelir: t çubuğundaki bir sinyal bir bayrak ayarlar ve gerçekleşme
open[t+1]fiyatında olur.
Döngü içinde pozisyon büyüklüğü
Riske dayalı pozisyon büyüklüğü "Risk ve İşlem Yönetimi" (2. ders) ve "Sistematik Trading" (9. ders) kurslarında öğretilmişti. Kodda bu tek bir satırdır: size = floor(equity * risk_pct / (entry - stop)); burada payda hisse başına risktir (burada 2 * ATR). Çok küçük bir ATR'nin hesabın taşıyamayacağı bir pozisyon yaratmaması için size * entry <= 0.25 * equity gibi bir üst sınır ekleyin.
İşlemleri R cinsinden kaydetmek
Kapanan her işlem; tarihler, fiyatlar, büyüklük, euro cinsinden kâr ve R-katı = kâr / (büyüklük × hisse başına risk) değerlerini içeren bir sözlük olarak eklenir. pd.DataFrame(trades), listeyi 9. dersteki metrik fonksiyonları ve "Risk ve İşlem Yönetimi" kursundaki (1. ders) beklenen değer hesaplaması için bir işlem tablosuna dönüştürür.
Asgari bir motor
def run(df, risk_pct=0.01, atr_mult=2.0, start_cash=20_000):cash, pos, entry, stop, rps = start_cash, 0, None, None, Nonetrades, equity, pending = [], [], Falsefor i in range(1, len(df)):o, h, l, cl, atr = df.open[i], df.high[i], df.low[i], df.close[i], df.atr[i]if pos > 0 and l <= stop: # çıkış: stop veya fiyat boşluğufill = min(o, stop)pnl = pos * (fill - entry)trades.append(dict(exit=df.index[i], pnl=pnl, R=pnl / (pos * rps)))cash += pos * fill; pos = 0if pending and pos == 0: # giriş: bu çubuğun açılışındaentry, rps = o, atr_mult * df.atr[i-1]pos = int(cash * risk_pct // rps)stop = entry - rps; cash -= pos * entry; pending = Falseif pos == 0 and df.signal[i]:pending = True # işlem bir sonraki açılıştaequity.append(cash + pos * cl)return pd.DataFrame(trades), pd.Series(equity, index=df.index[1:])
İki ayrıntı: pozisyon büyüklüğü için kullanılan ATR, girişten önceki akşam bilinen değer olan df.atr[i-1]'dir ve stop kapanışa göre değil en düşüğe göre kontrol edilir. İz süren bir stop, çıkış bloğundan sonra eklenen tek bir satırdır: stop = max(stop, cl - rps). Maliyetler 7. dersteki gibi pnl'den düşülebilir; burada anlaşılırlık için dahil edilmemiştir.
Çözümlü örnek
Varsayımsal örnek: başlangıç sermayesi €20,000, işlem başına risk 1 % (€200), stop 2 × ATR'de. Fiyatlar ve ATR uydurma yuvarlak sayılardır; ücretler, spread ve vergiler hariçtir.
- 1. işlem. Pazartesi sinyal; salı açılışı €50.00, önceki ATR €2.50. Hisse başına risk = 2 × 2.50 = €5.00; stop = €45.00. Büyüklük = floor(200 / 5) = 40 hisse (€2,000'lık pozisyon, sermayenin 10 %'u, 25 %'lik üst sınırın içinde). Daha sonra bir sinyalle €58.00'dan çıkış: kâr = 40 × 8 = €320 = 320 / 200 = +1.6R.
- 2. işlem. Aynı kurulum, giriş €50.00, stop €45.00, 40 hisse. Gece gelen haber: hisse €43.00'dan açılıyor. Motor min(açılış, stop) = €43.00'dan gerçekleştirir. Kayıp = 40 × 7 = €280 = −1.4R; planlanan −1.0R değil. Vektörleştirilmiş bir test −1.0R gösterir ya da hiçbir şey göstermezdi.
- 3. işlem. Giriş €50.00, iz süren stop; en düşük fiyat stopa dokunduğunda stop €47.50'ye yükselmiştir. Kayıp = 40 × 2.50 = €100 = −0.5R.
- İşlem listesi. R-katları +1.6, −1.4, −0.5: toplam −0.3R, ortalama −0.1R. Üç işlem hiçbir şey kanıtlamaz, ancak tablo yüzlerce işlem için doğru biçimdedir.
€120 fiyatlı ve ATR'si €6 olan ikinci bir enstrüman floor(200 / 12) = 16 hisse verir: aynı €200 risk, volatilite daha yüksek olduğu için daha az hisse.
Sık yapılan hata
if l <= stop: fill = stop gibi bir kod, piyasanın stopunuzda işlem gördüğünü fark ettirmeden varsayar. Fiyat boşluğunda görmemiştir. Long çıkışlar için her zaman min(open, stop) (short'lar için max(open, stop)) kullanın. Aynı mantık stop emirli girişler için de geçerlidir: €52'deki bir alış-stop emri, açılış €54 ise açılıştan gerçekleşir.Uygulama etkinliği
Kâğıt üzerinde motoru tek bir işlem için izleyin: sermaye €15,000, risk 1.5 %, girişten önceki akşamki ATR €1.80, stop çarpanı 2.5, bir sonraki açılışta giriş €36.00. (a) Hisse başına riski, stop seviyesini ve pozisyon büyüklüğünü (aşağı yuvarlayarak) hesaplayın. (b) Çıkış günü €37.00'dan açılıyor, €31.00'lık en düşüğe kadar iniyor ve €32.00'dan kapanıyor. Gerçekleşme fiyatı, euro cinsinden kâr ve R-katı nedir? (c) Stopu en düşük yerine kapanışa göre kontrol etseydiniz sonuç farklı olur muydu?
Çözümü göster
(a) İşlem başına risk = 0.015 × 15,000 = €225. Hisse başına risk = 2.5 × 1.80 = €4.50. Stop = 36.00 − 4.50 = €31.50. Büyüklük = floor(225 / 4.50) = 50 hisse.
(b) €37.00'lık açılış stopun üzerindedir, dolayısıyla fiyat boşluğu yoktur; €31.00'lık en düşük €31.50'de veya altındadır, dolayısıyla gerçekleşme fiyatı min(37.00, 31.50) = €31.50'dir. Kayıp = 50 × (31.50 − 36.00) = −€225 = −1.0R.
(c) Kapanışı (€32.00) kontrol etmek burada da çıkışı tetiklerdi, ancak €31.50 yerine €32.00'dan; dolayısıyla kayıp €200 (−0.89R) olur ve gerçekte olduğundan daha iyi görünürdü. Diğer çubuklarda en düşük fiyat stopa değerken kapanış stopun üzerine toparlanabilir; kapanışa dayalı bir kontrol bu durumda gerçek bir çıkışı tamamen kaçırır.
Sınırlamalar: günlük çubuklardan en yüksek ve en düşük fiyatın gün içindeki sırası bilinemez; stop ve bir hedef aynı çubuğun içinde kalıyorsa daha kötü sonucu varsayın.
Önemli çıkarımlar
- Kurallar izlenen yola bağlı olduğunda bir döngü motoru kullanın: stoplar, iz süren stoplar, riske dayalı pozisyon büyüklüğü ve kısmi çıkışlar.
- Her çubuk için olayların sırasını sabitleyin: çıkışlar, stop güncellemeleri, ardından bir sonraki açılışta girişler.
- Büyüklüğü sermaye × risk %'sinin hisse başına riske bölünmesiyle ve bir pozisyon üst sınırıyla belirleyin; her işlemi R-katıyla birlikte saklayın.
- Fiyat boşluğuyla gelen çıkışları stoptan değil açılıştan gerçekleştirin; 1R'den büyük kayıplar buradan gelir.
Sonraki adım
9. ders, artık ürettiğiniz sermaye eğrisini ve işlem listesini yeniden kullanılabilir, test edilmiş performans fonksiyonlarına dönüştürüyor: CAGR, düşüş, Sharpe, Sortino ve kâr faktörü.
Öz değerlendirme
Soruları yanıtlayın, ardından yanıtlarınızı kontrol edin. İstediğiniz kadar tekrar deneyebilirsiniz.
Kendi tekrarınız için otomatik öz değerlendirme. Cevaplarınız tarayıcınızda kontrol edilir; bunları görmez ve değerlendirmeyiz. Bu bir sınav veya yeterlilik değildir.
İlerlemeniz
“Tamamlandı” yalnızca dersi bitirdiğinizi işaretlediğiniz anlamına gelir. Anlayışınızın bir sınavı değildir. İlerleme ve notlar yalnızca bu cihazdaki bu tarayıcıda saklanır — bir hesapta değil.