İçeriğe geç
Seçkin Can Şahin

Kâr etmeyen arbitraj botu: 95.062 ölçüm, iki dakikalık fırsat

2017–2019 arasında Kraken ile BTCTurk fiyatlarını karşılaştıran bir arbitraj botu yazdım. On beş aylık kayıtta 95.062 ölçüm var; fark, paranın taşınma maliyetini yalnızca 180 ölçümde geçti.

5 dakikalık okuma

2017 ile 2019 arasında, akşamları, bir kripto arbitraj botu yazdım. Kraken’in dolar fiyatıyla BTCTurk’ün lira fiyatını karşılaştırıyor, aradaki oranı hesaplıyor, fark yeterince açıldığında ses çıkarıyordu. Yanında bir alım satım simülatörü, piyasa değerine göre ağırlıklandırılmış bir ilk on fonunu takip eden bir araç, wxPython ile çizilen canlı bir grafik ve Ethereum madencilik makinelerine (rig) bağlanıp üretim durduysa makineyi yeniden başlatan bir betik vardı.

Klasördeki readme dosyasını da ben yazmışım. Simülatörü anlatan satır, dosyadaki hâliyle:

ise yarar diyodum ama bi getirisi olmuyor gorunuyor.

Yazım hatalarıyla birlikte bıraktım, çünkü cümlenin kendisi doğru. Bot çalışmadı. Neden çalışmadığı ise hâlâ diskte duruyor: 95.062 satırlık bir kayıt dosyası.

Simülatörün mantığı üç satırdı

Simülatör beş saniyede bir üç yere bakıyordu: BTCTurk’ün ETH/TL emir defterindeki en iyi alış ve satış, Kraken’in ETH/USD makas (spread) verisi, bir de dolar kuru. İkisini aynı para birimine getirip oranı buluyordu.

Kural basitti. BTCTurk’teki alış fiyatı Kraken’in %0,7 altına düşerse al, satış fiyatı %0,7 üstüne çıkarsa sat. Her işlemden %0,4 komisyon düş. Aynı yönde art arda işlem yapmamak için on beş saniye bekle. Tek seferde en fazla 1.000 lira al, en fazla 0,25 ETH sat.

Portföy 10.000 lira ve 2,5 ETH ile başlıyordu. Her turun sonunda betik iki sayıyı yan yana basıyordu: portföyün başlangıca oranı ve ETH fiyatının başlangıca oranı. Yani kendini “hiçbir şey yapmayıp elimdekini tutsaydım” senaryosuyla karşılaştırıyordu. Kodun en faydalı satırı buydu, cevabı da o verdi.

Maliyet yığını: %4,07

Asıl bilgi simülatörde değil, alarm betiğindeydi. Orada paranın bir borsadan diğerine gitmesinin kaça mal olduğunu tek tek yazmışım:

BANK_CONVERSION_CHARGE = 1.00
TRANSFER_LOSS_MULTIPLIER = 1.0/500.0
MAIN_EXCHANGE_MARKET_TRADE_COMISSION_LOSS = 2.0/1000
TURKEY_MARKET_TRADE_COMISSION_LOSS = 1.5/1000
SENDING_METHOD_COST = 1.035

Sırasıyla: kur dönüşümünde kayıp yok; coin’i zincir üzerinden göndermek, ortalama 0,5 BTC’lik bir emirde %0,2; yurt dışındaki borsanın işlem komisyonu %0,2; Türkiye tarafındaki satış komisyonu %0,15; son satır da parayı içeri sokmanın maliyeti.

En önemlisi o son satır. Kredi kartıyla para yatırmak %3,5’e mal oluyordu. Havale çok daha ucuzdu — yanına düştüğüm nota göre ilk transferimde %0,45. Hepsi çarpıldığında kartla giden yolun toplam maliyeti %4,07, havaleyle giden yolun %1,01 çıkıyor.

Aradaki fark bir ücret farkı değil, zaman farkı. Kart anında, havale ertesi gün. Hızlı yol pahalı, ucuz yol yavaş. Arbitraj tam olarak bu iki cümlenin arasında ölür.

95.062 ölçüm, sekiz kez

Alarm betiği 14 Şubat 2018 ile 22 Mayıs 2019 arasında iki borsa arasındaki oranı bir dosyaya yazdı. Uzun süre ayakta duran bir servis değildi; crontab’a dakikada altı kez, on saniye arayla yeniden başlatacak şekilde koymuştum. Dosyada 95.062 ölçüm var.

Ortanca değer 0,9998. Yani tipik bir anda iki piyasa, binde iki hata payıyla aynı fiyatı söylüyordu. Ölçümlerin %99’u 1,0345’in altında kalıyor.

Alarmın eşiğini %5’e koymuşum. On beş ayda bu eşik sekiz kez geçildi. Sekizinden biri 3,9 gibi imkânsız bir değer, yani bozuk bir fiyat okuması. Altısı 8 Mart 2018 gecesi saat üçte art arda gelen ölçümler: yaklaşık iki dakikalık tek bir pencere.

Kart yolunun maliyeti olan %4,07’yi geçen ölçüm sayısı 180. Havale yolunun maliyeti olan %1,01’i geçen ölçümler kaydın yaklaşık dörtte biri — ama o parayı ancak ertesi gün taşıyabiliyorsunuz ve fark ertesi güne kadar yerinde durmuyor.

Strateji bu üç sayının içinde bitiyor. Fark ya maliyeti aşmıyor, ya da aştığı anda oraya yetişemiyorsunuz.

Emrin dolduğunu varsaymak

Simülatörün içinde kendi yazdığım bir yorum satırı var:

# we assume that if you spend just a little bit more than the best bid, you get to buy it

En iyi alış fiyatının biraz üstünü verirseniz alabildiğinizi varsayıyoruz.

Simülasyonu gerçeklikten ayıran şey bu tek varsayım. Gerçekte en iyi alış bir fiyat değil, o fiyattaki miktar kadar bir fiyattır. Emriniz o miktarı geçtiği anda fiyat aleyhinize kayar ve kayan fiyat, kovaladığınız %0,7’nin içinden çıkar. Simülatör bunu göremiyordu, çünkü emir defterinin derinliğine hiç bakmıyordu; sadece en üst satırı okuyordu.

Yanına iki şey daha koyun. Dolar/lira kurunu bir bankanın günlük kur sayfasından çekiyordum, yani saniyede değişen bir farkı günde bir kez güncellenen bir sayıyla hesaplıyordum. BTCTurk’ün fiyat ucuna doğrudan erişimim de yoktu; Cloudflare’ın arkasındaki genel sayfayı bir kazıyıcıyla okuyordum ve okuduğum fiyatın kaç saniye eski olduğunu hiçbir zaman bilmedim.

Bunların hiçbiri geriye dönük testte (backtest) görünmez. Geriye dönük test piyasayı çalıştırmaz, sizin yazdığınız varsayımları çalıştırır.

Gündüz mikro saniye, akşam beş saniye

Bu botu yazdığım dönemde, Haziran 2017 – Mart 2018 arasında ICY Capital’da çalışıyordum: Chicago merkezli bir yüksek frekanslı işlem firması. Trader’ların kullandığı arayüzü Python’la sıfırdan yazdım; C ile yazılmış strateji tarafında verinin saklanması, işlenmesi ve aktarılması için iyileştirmeler yaptım.

Yani gündüzleri, gecikmenin sonradan düşünülen bir ayrıntı değil mimarinin kendisi olduğu bir sistemin yanında duruyordum. Akşamları eve gelip time.sleep(5) yazıyordum.

O zaman bu ikisini aynı problem olarak görmedim. Gündüzkü iş “altyapı”, akşamki iş “fikir” gibi geliyordu. Oysa arbitrajda fikir diye ayrı bir şey yoktur. Fikir, maliyet ve gecikme çıkarıldıktan sonra geriye kalan şeydir; ikisini çıkarmadan elinizde kalan fikir değil, grafiktir.

Çalışmayan şeyler yapmak

Bu bot akşamlarıma mal oldu. Ürettiği tek şey bir kayıt dosyası oldu ve sorunun cevabı da o dosyanın içindeydi.

Yanlış yaptığım şey botu yazmak değil, sırayı ters kurmaktı. Önce kodu yazdım, sonra maliyet yığınını çıkardım, en son farkın dağılımını ölçtüm. Doğru sıra tam tersi. Maliyet yığınını yazmak bir öğleden sonra sürer, dağılımı ölçmek bir hafta. İkisi bittiğinde hangi kodun yazılacağı — ya da yazılmayacağı — kendiliğinden belli olur.

Aynı sorunun profesyonel hâline altı yıl sonra döndüm. Kasım 2024’te LeanScale için iki ayda bir kripto işlem platformu yazdım; 35.000 satırlık JavaScript sistemi Rust’a çevirdim ve amaç en azından Solana ağı üzerinde kârlı işlem yapmaktı. Detayını paylaşamıyorum.

Klasörü silmedim. İçindeki en değerli satır kod değil, readme’deki o cümle. Çalışmayan projeler bu işin anormal kısmı değil; anormal olan, çalışmadığını kendinize yazılı olarak hiç söylememek.

Buraya kadar okuduysan

Bunun gibi yazıları yayımladığımda e-postana göndereyim. Ayda birkaç kez. Yapay zeka, mühendislik ve yatırım üzerine. Spam yok.

Ayda birkaç kez. Yapay zeka, mühendislik ve yatırım üzerine. Spam yok.

Yorumlar

Burada henüz kimse konuşmamış. İlk sözü siz söyleyin — katılmadığınız yeri yazarsanız daha da iyi.

Yorum yazın

Yorumlar önce bana geliyor. Onayladığımda burada, adınızla birlikte yayımlanıyor.

Yayımlanmaz. Sadece gerekirse size dönebilmek için.