CODESCRIPT

Boş değer (na) ile çalışmak

Bir gösterge her barda bir sayı üretemez; arkasında yeterli geçmiş yoksa sonuç boş kalır ve CodeScript buna na der. Bu sayfa boş değerin nereden geldiğini, nasıl sınandığını ve çizgiyi neden kopardığını anlatır.

Boş değer bir hata değildir. "Bu barda söyleyecek bir şeyim yok" demenin dildeki karşılığıdır. 20 barlık bir ortalama, arkasında 20 bar birikmeden sayı veremez; o yüzden ilk barlarda na döner.

Boş değer nedir?

na, sıfır değildir. Sıfır gerçek bir ölçümdür; na ise ölçümün hiç yapılamadığını söyler. Bu iki şeyi karıştırmak, ilerideki hataların çoğunun kaynağıdır.

  • na bir sayı değildir; ona dokunan her işlem yine na verir.
  • Boş bir koşul yanlış (false) sayılır; hata vermez, sessizce öbür dala düşer.
  • plot bir barda boş değer görürse orayı çizmez, çizgide boşluk kalır.
CODESCRIPT
ortalama = sma(close, 20)
// ilk 19 barda geride 20 bar yok, sonuc bos kalir
plot(ortalama, "SMA20", "#2962ff")
plot(close, "fiyat", "#787b86")

Gri fiyat çizgisi ilk bardan başlar, mavi ortalama çizgisi ise 20. bardan itibaren belirir; öncesinde grafikte tek bir mavi nokta bile yoktur.

NOT

Isınma dönemi göstergenin uzunluğuna bağlıdır. sma(close, 20) için 19 bar, sma(close, 200) için 199 bar boş geçer. Uzun periyot seçmek, grafiğin başında uzun bir sessizlik demektir.

Gösterge neden ilk barlarda boş döner?

Bir gösterge geçmişe bakarak hesap yapar. sma(close, 50) elli barlık bir pencere ister; pencere dolmadan ortalama alınamaz. Aynı mantık geriye bakan her işlev için geçerlidir.

  • sma, ema, stdev gibi pencereli göstergelerde ilk uzunluk-1 bar boştur.
  • prev(close, 1) ilk barda boştur; ondan öncesinde bar yoktur.
  • change(close, 1) da ilk barda boştur; farkı alınacak ikinci değer henüz yoktur.
  • barssince(kosul) koşul hiç gerçekleşmemişken boş kalır.
  • sqrt ve log gibi işlevler tanımsız girdide boş döner; sqrt(-1) na verir.
CODESCRIPT
kisa = sma(close, 10)
uzun = sma(close, 50)
// yesil cizgi 10. bardan, kirmizi cizgi 50. bardan itibaren dolar
plot(kisa, "SMA10", "#26a69a")
plot(uzun, "SMA50", "#ef5350")

Yeşil çizgi 10. barda, kırmızı çizgi 50. barda başlar; aradaki kırk barda grafikte yalnız yeşil çizgi vardır. İki çizginin kesişimini bekleyen bir kural 50. bardan önce hiç çalışamaz.

DİKKAT

Kuralın en uzun göstergen kadar geç başlar. Geriye dönük sınamada ilk işlemin neden bu kadar geç açıldığını merak ediyorsan, önce en uzun periyoduna bak.

na ile karşılaştırma neden çalışmaz

Boş değer hiçbir şeye eşit değildir, kendisine bile. Bu yüzden deger == na yazdığında sonuç her zaman yanlış çıkar ve tek bir boş barı bile yakalayamazsın. Sınamanın yolu na() işlevidir.

CODESCRIPT
ortalama = sma(close, 50)
// YANLIS: bos deger kendisine bile esit degildir, bu satir hep false doner
yanlis = ortalama == na
// DOGRU: na() bir degerin bos olup olmadigini sinar
dogru = na(ortalama)
plot(iff(yanlis, 1, 0), "yanlis kontrol", "#ef5350", "kontrol")
plot(iff(dogru, 1, 0), "dogru kontrol", "#26a69a", "kontrol")

Alt panelde kırmızı çizgi baştan sona 0'da düz kalır; boş barları hiç görmez. Yeşil çizgi ilk 49 barda 1, 50. bardan sonra 0 olur ve boş dönemi tam olarak işaretler.

na(deger)

Verilen değer boşsa true, dolusa false. Tek başına yazılan na ise boş değerin kendisidir.

deger
seri
Boş olup olmadığı sınanacak değer ya da seri.
DİKKAT

na'yı sayı gibi kullanma. ortalama > na ya da ortalama != na gibi karşılaştırmalar hata vermez ama hiçbir zaman doğru da olmaz; kodun sessizce yanlış çalışır.

Boş değer hesaba bulaşır

na ile yapılan her işlem yine na verir. Bir yerde başlayan boşluk, ona dokunan bütün hesaplara yayılır. Zincirin sonundaki çizgi boş kalıyorsa kaynağını zincirin başında ara.

CODESCRIPT
uzun = sma(close, 200)
// uzun bos oldugu surece fark da bostur, close dolu olsa bile
fark = close - uzun
oran = fark / uzun
plot(oran, "ortalamaya uzaklik", "#2962ff", "uzaklik")

Alt panelde çizgi ilk 199 barda hiç görünmez, 200. barda birden başlar. close her barda dolu olduğu hâlde çizgi boş kalır; boşluğu 200 barlık ortalama taşımaktadır.

İPUCU

Boş bir çizgiyi ayıklarken zinciri adım adım çiz. Önce ham göstergeyi, sonra farkı, sonra oranı çizersen boşluğun hangi adımda başladığını gözünle görürsün.

nz ile boş değeri sayıya çevirmek

nz, boş değerlerin yerine seçtiğin sabit bir sayıyı koyar; sabit vermezsen 0 kullanır. Dolu barlara dokunmaz. Tek bir boş barın koca bir toplamı bozacağı yerlerde doğru araç budur.

nz(source, replacement=0)

Boş değerlerin yerine replacement konmuş, aynı uzunlukta bir seri.

source
seri
Boşluk içerebilen kaynak seri.
replacement
sayı
Boş değerin yerine konacak sabit; verilmezse 0 kullanılır.
CODESCRIPT
degisim = change(close, 1)
// ilk barda change bostur; 0 sayarsak birikim ilk bardan itibaren calisir
birikim = cum(nz(degisim, 0))
plot(birikim, "birikimli degisim", "#2962ff", "birikim")

Alt panelde birikimli değişim çizgisi ilk bardan itibaren 0'dan başlayarak akar. nz olmasaydı ilk bardaki boşluk toplamın tamamını boş bırakırdı.

DİKKAT

nz'yi her yere serpme. 0 gerçek bir sayıdır ve karşılaştırmaya girer. Isınma barlarında ortalamayı 0 yaparsan fiyat her barda ortalamanın üstünde görünür ve olmayan alım sinyalleri doğar.

CODESCRIPT
uzun = sma(close, 200)
// YANLIS: isinma boyunca uzun=0 olur, close her zaman 0'in ustundedir
sahte = close > nz(uzun, 0)
// DOGRU: once bos mu diye sor, bossa kural hic calismasin
gercek = not na(uzun) and close > uzun
plotshape(sahte, style="circle", location="abovebar", color="#ef5350")
plotshape(gercek, style="triangleup", location="belowbar", color="#26a69a")

İlk 199 barın her birinin üstünde kırmızı bir daire çıkar ve hiçbiri gerçek sinyal değildir. Yeşil üçgen ise yalnız 200. bardan sonra, ortalama gerçekten dolduğunda bar altında belirir.

İPUCU

Kural yazarken sorulacak doğru soru şudur: bu bar için gerçekten bir cevabım var mı? Varsa hesapla, yoksa hiçbir şey yapma. nz bu soruyu atlar ve uydurma bir cevap verir; onu yalnız uydurma cevabın zararsız olduğu yerde kullan.

fixnan ile son bilinen değeri taşımak

Bazen boşluğu sabit bir sayıyla değil, serinin son bilinen değeriyle doldurmak istersin. fixnan tam olarak bunu yapar: her boş bara, o noktaya kadar görülen son dolu değeri koyar. İlk dolu değere kadar boşluk sürer, çünkü taşınacak bir şey henüz yoktur.

fixnan(source)

Aynı uzunlukta seri: her boş bar, o noktaya kadarki son dolu değeri taşır.

source
seri
İleri taşınacak, boşluk içerebilen seri.
CODESCRIPT
// yalnizca yukari kesisim barlarinda deger uret, digerlerini bos birak
sinyal = iff(crossover(close, sma(close, 20)), close, na)
// son sinyal fiyatini bir sonraki sinyale kadar tasi
tasinan = fixnan(sinyal)
plot(tasinan, "son sinyal fiyati", "#ff9800")

Turuncu çizgi basamak basamak ilerler: her yukarı kesişimde yeni bir seviyeye atlar ve bir sonraki kesişime kadar orada yatay durur. İlk kesişimden önce hiç çizilmez.

NOT

nz ile fixnan'ı karıştırma. nz her boş bara hep aynı sabiti koyar; fixnan ise verinin kendi ürettiği son değeri koyar. Biri sabit, öteki serinin kendi geçmişi.

Çizgi neden kopuyor, nasıl birleşir

plot boş bir barı atlar. Serinin ortasında boşluk varsa çizgi orada kopar ve grafikte kesik kesik bir görüntü çıkar. Bu bazen tam istediğin şeydir, bazen de kusurdur; hangisi olduğuna sen karar verirsin.

iff(condition, ifTrue, ifFalse)

Her bar için, koşul doğruysa ifTrue değeri, değilse ifFalse değeri.

condition
koşul
Her barda ayrı ayrı değerlendirilen koşul.
ifTrue
seri
Koşul doğruyken alınacak değer; buraya na yazarak o barı bilerek boş bırakabilirsin.
ifFalse
seri
Koşul yanlışken alınacak değer.
CODESCRIPT
// yalnizca hacmi ortalamanin ustunde olan barlarda deger uret
yogun = iff(volume > sma(volume, 20), close, na)
// kopuk hali: bos barlarda cizgi kesilir
plot(yogun, "yogun barlar", "#ef5350")
// butun hali: son deger tasindigi icin cizgi kesilmez
plot(fixnan(yogun), "surekli", "#2962ff")

Kırmızı çizgi yalnız yüksek hacimli barlarda görünür ve aralarda kopar. Mavi çizgi aynı değerleri kullanır ama boşlukları son bilinen fiyatla doldurduğu için baştan sona kesintisizdir.

  • Çizgi bütün olsun istiyorsan: fixnan ile son değeri taşı.
  • Boşluğa sabit bir taban uyuyorsa: nz ile doldur. Hacimde 0 anlamlı bir tabandır.
  • Kopukluk zaten istediğin şeyse: dokunma. Yalnız sinyal barlarını nokta nokta göstermek için iff(kosul, fiyat, na) doğru kalıptır.
  • Isınma barları grafiği bozuyorsa: göstergenin uzunluğunu kısalt ya da grafiği daha derin veriyle aç.
İPUCU

Ayrık işaretler için plot yerine plotshape ya da plotchar daha temizdir. Onlar koşulun boş olduğu barda zaten hiçbir şey çizmez, dolayısıyla kopuk çizgi sorunu hiç doğmaz.

Sık yapılan hatalar

  • deger == na yazmak. Bu satır hiçbir zaman doğru olmaz; na(deger) kullan.
  • na'yı 0 sanmak. 0 gerçek bir ölçümdür, na ölçümün yokluğudur.
  • Her boşluğu refleksle nz(x, 0) ile kapatmak. Bu, ısınma barlarında sahte sinyal üretir.
  • Boş koşulun hata vereceğini beklemek. Boş koşul sessizce yanlış sayılır; kod çalışır ama sonuç yanlıştır.
  • Kopuk çizgiyi çizim kusuru sanmak. Çoğu zaman kaynak seride gerçek boşluk vardır; önce seriye bak.
  • Uzun periyotlu bir göstergeyi kısa geçmişli bir grafikte kullanmak. sma(close, 200), 200 bardan kısa bir grafikte baştan sona boş kalır.
NOT

Boş değer, geriye dönük sınamanın da bir parçasıdır. Kuralın ısınma bitmeden çalışamayacağı için ilk işlem her zaman biraz geç açılır; bu bir kusur değil, dürüst bir sonuçtur.