Yeni bir kripto algoritma geliştirdin. Çok kazançlı olacağını düşünüp, bir an önce canlı ortamda al-sat yapmak istiyorsun. Peki canlı ortamda denemeden önce geliştirdiğin algoritmanın geçmiş verilerle nasıl sonuç vereceğini, kazançlı olup olmadığını öğrenmek istemez misin? Backtesting sayesinde, yani geçmiş verilerle kripto algoritmanı çalıştırıp verimini, karlılığını görebilirsin.
Böylece bir sürü zaman ve para kaybından kurtulursun.
Yeni bir Kripto Bot çatısı olan Jesse ile kripto algoritmanı kolaylıkla test edebilirsin. Piyasada zipline ve backtrader gibi benzer işi yapan farklı kütüphaneler var. Fakat adı geçen kütüphanelerin yapısının karmaşıklığından dolayı öğrenmesi daha zordur.
Jesse ise basitliği, anlaşılırlığı ve kolay kullanımı sayesinde benim gözümde diğerlerinden birkaç adım ilerisinde durmaktadır.
Jesse Çatısının diğer bir harika özelliği ise binance ve bitfinex gibi yaygın kullanılan borsalarla entegre olması. Dolayısıyla verileri çekmek için ekstra bir efor harcamak gerekmiyor.
Jesse sadece bir backtesting çatısı değil, aynı zamanda ileri de canlı da trade yapabilmeye olanak sağlayacak bir araç. Canlı trade kısmı henüz geliştirilme aşamasında. Bittiği zaman, testlerinizi çalıştırdığınız gibi aynı stratejiyi canlı trade için de kullanabileceksiniz.
Jesse Çatısının Kurulumu
Kuruluma geçmeden önce sisteminizde öncelikle bulunması gereken yazılım ve servisleri görelim:
- Python >= 3.6
- pip >= 19.3.0
- PostgreSQL >= 10
- ta-lib >= 0.4
Jesse bir python kütüphanesi olduğu için, dolayısıyla sistemde Python kurulu olması gerekiyor. Pip, paket kurulumu için gerekiyor.
Geçmiş verileri saklamak için de bir PostgreSQL veritabanı servisine ihtiyacımız var. Ta-lib kütüphanesini önceki kripto bot ile ilgili yazılarımda anlatmıştım. Jesse, indikatörleri hesaplamak için bu kütüphaneyi kullanıyor.
Dolayısıyla ta-lib kütüphanesini sistemimize kurmamız gerekiyor.
TA-lib Windows kurulumu
Windows 10 makinasında kurulumu en kolay bir şekilde, binary dosyasını aşağıdaki siteden python sürümünüzle uyumlu olanı indirerek yapabilirsin.
https://www.lfd.uci.edu/~gohlke/pythonlibs/
Yukarıdaki siteden kendi python (3.6) sürümümle uyumlu olan TA_Lib‑0.4.18‑cp36‑cp36m‑win_amd64.whl dosyasını indirdim.
Siz bu dosya yerine hangi python sürümünü kullanıyorsanız onunla uyumlu sürümü indirin.
Kurulum için pip ya da pip3, hangisi sizin için geçerliyse onu kullanın.
Dosyayı indirdikten sonra, pycharm terminal ekranından pip3 install diyerek kurulumu gerçekleştiriyorum:
pip3 install TA_Lib-0.4.17-cp36-cp36m-win_amd64.whl
TA-lib Linux Kurulumu
Linux üzerinde TA-lib çalıştırabilmeniz için öncelikle Ta-lib c kütüphanesini kurmanız gerekiyor.
Ta-lib c kütüphanesini indirin:
wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar -xzf ta-lib-0.4.0-src.tar.gz
cd ta-lib/
./configure --prefix=/usr
make
sudo make install
Bu işlemi tamamladıktan sonra ta-lib python paketini yükleyelim:
pip3 install ta-lib
Jesse ile bağlantılı paketleri yükleyin
pip3 install -r https://raw.githubusercontent.com/jesse-ai/jesse/master/requirements.txt
Nihayet sıra geldi Jesse’nin kendisini kurmaya 🙂
pip3 install jesse
Genel olarak kurulum biraz zahmetli olsa da bir kere yaptıktan sonra geri dönüp bakma ihtiyacınız olmayacaktır.
Yeni Jesse Projesi Oluşturalım
Kendi stratejinizi oluşturmak için yeni bir Jesse projesi oluşturun:
jesse make-project projenin_ismi
Bu komut ile projenizin temel iskeleti oluşmuş olacaktır.
Projenin Konfigürasyonu
PostgreSQL Konfigürasyonu
Projenin kök dizininde bulunan config.py dosyasını açarak, postgresql bağlantı bilgilerini giriniz:
Config.py (örnek bağlantı), kendi postgresql bilgilerinizle değiştirin:
---
'databases': {
'postgres_host': '127.0.0.1',
'postgres_name': 'jesse_db',
'postgres_port': 5432,
'postgres_username': 'jesse_user',
'postgres_password': 'mypassword',
},
---
Zaman Çerçevesi (time interval), Borsa (exchange) ve Kripto Para (Pair) Ayarı
Stratejimizin hangi zaman aralığı, borsa ve kripto para ikilisi üzerinde çalışacağını belirtmek için, routes.py dosyasında rota tanımlamak gerekiyor.
routes.py:
---
# trading routes
routes = [
('Binance', 'BTCUSDT', '4h', 'ExampleStrategy'),
]
---
Örneğimizde stratejimizi Binance borsası üzerinde BTCUSDT verilerini 4 saatlik (4h) zaman aralığı için çalıştırmış olacağız. ExampleStrategy olarak belirtilen kısmı daha sonra kendi stratejimizin ismi ile değiştireceğiz.
Proje ile hazır gelen örnek strateji şablonuna bakalım:
from jesse.strategies import Strategy
class ExampleStrategy(Strategy):
def should_long(self) -> bool:
return False
def should_short(self) -> bool:
return False
def should_cancel(self) -> bool:
return False
def go_long(self):
pass
def go_short(self):
pass
should_long methodunda hangi durumda long emri vereceğinizi, should_short metodunda hangi durumda shortlayacağınızı belirtiyorsunuz.
go_long methodunda long’a girerken, değerleri belirtiyorsunuz. Alış fiyatı, miktarı, stop loss değeri vs…
Kendi Stratejimizi Oluşturalım
Yukarıda bahsettiğim metodların ne işe yaradığını görmek için kendi stratejimizi oluşturalım.
Jesse’nin make-strategy komutuyla yeni bir strateji dosyası oluşturalım, ismi de MacdCrossStrategy olsun.
Jesse make-strategy MacdCrossStrategy
MacdCrossStrategy sınıfında örnek olması açısından basit bir algoritma seçiyoruz. Macd indikatörünü baz alarak, hızlı çizginin yavaş olanı yukarı yönlü kesmesi durumunda al sinyali üretiyoruz, tersi durumda, hızlı çizginin yavaş olanı aşağı yönlü kesmesi durumunda sat sinyali üretiyoruz.
from jesse.strategies import Strategy
from jesse import utils
import jesse.indicators as ta
class MacdCrossStrategy(Strategy):
@property
def current_macd(self):
return ta.macd(self.candles)
@property
def previous_macd(self):
return ta.macd(self.candles[:-1])
def should_long(self) -> bool:
current_macd = self.current_macd.macd
current_signal = self.current_macd.signal
previous_macd = self.previous_macd.macd
previous_signal = self.previous_macd.signal
# # Yukari yonlu cakisma var mı kontrol ediyorum?
# if current_macd > current_signal and previous_macd < previous_signal:
# return True
# Yukari yonlu cakisma var mı kontrol ediyorum?
if current_macd > current_signal and previous_macd < previous_signal:
return True
return False
def should_short(self) -> bool:
return False
def should_cancel(self) -> bool:
return True
def go_long(self):
qty = 1
stop = entry - 2*self.atr
entry = self.price
self.buy = qty, entry
self.stop_loss = qty, stop
def update_position(self):
current_macd = self.current_macd.macd
current_signal = self.current_macd.signal
previous_macd = self.previous_macd.macd
previous_signal = self.previous_macd.signal
asagi_yonlu_cakisma_var = current_macd < current_signal and previous_macd > previous_signal
# Asagi yonlu cakisma varsa hepsini satiyorum
if self.is_long and asagi_yonlu_cakisma_var:
self.liquidate()
def go_short(self):
pass
Current_macd değeri ile son macd değerini alıyorum. Previous_macd değeri ile de bir önceki mumda son mum olarak kabul edip macd değerini buluyorum.
Çakışmayı kontrol ederek, al ya da sat sinyali üretiyorum. MacdCrossStrategy’sinde dikkatini çekmek istediğim nokta, hedef değerini başta go_long metodunda belirtmiyorum. Çünkü dinamik olarak satış yapmak istiyorum. Aksi durumda go_long metodunda aşağıdaki gibi bir ifade yazabilirdim:
Alternatif long giriş yöntemi:
def go_long(self):
# alış fiyatım o anki fiyat
entry = self.price
# stop değerim alış fiyatın atr’nin 2 katı aşağısı
stop = entry - 2*self.atr
# miktar
qty = 1
# hedefim
profit_target = entry + 5*self.atr
self.buy = qty, entry
self.stop_loss = qty, stop
self.take_profit = qty, profit_target
Bu şekilde yapmak yerine satışı macd aşağı yönlü keserse, satış yapsın diyebilmek için, update_position metodunu eklemiş oldum.
def update_position(self):
current_macd = self.current_macd.macd
current_signal = self.current_macd.signal
previous_macd = self.previous_macd.macd
previous_signal = self.previous_macd.signal
asagi_yonlu_cakisma_var = current_macd < current_signal and previous_macd > previous_signal
# Asagi yonlu cakisma varsa hepsini satiyorum
if self.is_long and asagi_yonlu_cakisma_var:
self.liquidate()
Artık stratejimiz hazır. Tekrar routes.py dosyasına gidelim ve orada MacdCrossStrategy sınıfını kullanacağımızı belirtelim:
…
# trading routes
routes = [
('Binance', 'BTCUSDT', '4h', 'MacdCrossStrategy'),
]
…
Artık test etmek istediğimiz stratejimiz hazır. Şimdi yapmamız gereken, geçmiş verileri veritabanımıza yüklemek. Aksi takdirde backtesting yapamayacağız.
Geçmiş Verileri Veritabanına Yüklemek
import-candles komutu ile verilerimizi yüklüyoruz:
jesse import-candles 'Binance' 'BTCUSDT' '2020-01-01'
Bu komutla 1 ocak 2020 tarihinden bugüne kadar olan tüm binance verilerini veritabanına yüklemiş olacağız.
Seçtiğiniz tarihe bağlı olarak biraz sürecektir.
Verilerimiz yüklendi, artık testimizi çalıştıralım.
Testi Çalıştırmak (Backtest)
jesse backtest ‘baslangic_tarihi’ ‘bitis_tarihi’ komutu ile testimizi başlatalım:
Jesse backtest ‘2020-06-01’ ‘2021-01-15’
Bu komut bize aşağıdaki gibi bir sonuç verecektir:
Gördüğünüz gibi sonuçlar basit bir stratejiye göre çok güzel. Bitcoin’in boğa sezonunda olmasının bir güzelliği 😊
10000 dolarımız 28839.45 dolara yükseldi.
Konsol üzerinde temel verileri böylece görebilmiş oluyorum.
Grafik Çıktı Almak
Jesse’nin daha da güzel bir özelliği de grafik üretmesi.
Jesse backtest ‘2020-06-01’ ‘2021-01-15’ –chart
Sonuna chart parametresini eklediğimizde, bize png formatında dosya çıktı üretecektir.
Ürettiği dosyaya bakalım şimdi de:
İlk grafikte bakiyemizin değişimini, ikincisi de fiyat hareketlerini gösteriyor.
Json, csv formatlarında da çıktı üretebiliriz.
Daha da güzel bir özelliği ise TradingView’da görebileceğimiz şekilde bir pine scripti üretmesi:
Jesse backtest 2020-06-01 2021-01-15 –tradingview
Üretilen dosyayı TradingView’da açalım:
Open menüsünden New blank strategy komutunu çalıştıralım:
Jesse’nin ürettiği dosyanın içeriğini editörün içerisine yapıştıralım:
Add to Chart komutunu çalıştırıp grafiğe eklemesini sağlayalım:
BackTesting Mevzusu Neden Önemlidir ve Sonuç
Algoritmanın geçmiş performansı gelecekte de benzer sonuçları üreteceğinin garantisini vermez. Bu bakımdan backtest canlı trade yapmanın yerini tutmaz. Fakat testlerde olumsuz bir performans gösteren algoritmanın gelecekte başarılı olacağını düşünmek hayalcilik olacaktır.
Bu bakımdan backtest yapmak bir filtre görevi görerek kazanç getirmeyecek algoritmaları eleme veya iyileştirme olanağı sunarak, bize zamandan ve paradan tasarruf ettirecektir.
Örnek projenin github adresi:
samplebacktesting: Basit bir kripto algoritmanın Jesse çatısı ile testi. (github.com)
Faydalanılan Kaynaklar
Resmi sitesi:
Jesse – The Open-source Python Bot For Trading Cryptocurrencies
Github adresi:
jesse-ai/jesse: An advanced crypto trading bot written in Python (github.com)
Ta-lib kurulumu:
How to Install TA-Lib on Ubuntu Server | Dominik Sachsenhofer
Jesse’nin kendi blogu çok faydalı. Tüm yazıların okunması elzem.
Basit bir python bot nasıl yazılır?
python ile kripto para al sat botu yazalım (trading bot): RSI, MACD, vs… (onbirkod.com)
Mrb komutlar doğru olduğu halde aşağıdaki hatayı alıyorum neden olabilir
Uncaught Exception: ValueError: ‘Binance’ is not a supported exchange
jesse import-candles ‘Binance’ ‘BTCUSDT’ ‘2020-01-01’
komutunu jesse import-candles Binance BTCUSDT 2020-01-01 bu şekilde denedim çalıştı
Neredeyse 15dk bekledim hala gelmedi 2020 verileri için bu kadar uzun mu sürüyor acaba ?
Jesse make-strategy MacdCrossStrategy ” yi çalıştıramıyorum. önceki kodlar normal çalışıyor. buraya geldiğimde böyle bir hata alıyorum. neden acaba?
(venv) C:\Users\Kullanıcı\PycharmProjects\pythonProject1>jesse make-strategy MacdCrossStrategy
←[31mCurrent directory is not a Jesse project. You must run commands from the root of a Jesse project.←[0m
projenin içine cd ile geçmeniz gerekiyor
Ustam devamı gelmedi makalelerin
stochastik rsi hakkında bir yazım olacak:
İlgin için teşekkür ederim.
File “C:\Users\user\AppData\Local\Programs\Python\Python39\lib\pydoc.py”, line 450, in safeimport
raise ErrorDuringImport(path, sys.exc_info())
=========================================================================
Uncaught Exception: ErrorDuringImport: problem in strategies.MacdCrossStrategy – NameError: name ‘self’ is not defined
Şöyle bir hata alıyorum ne yapabilirim
Talat Bey,
Emeğiniz için teşekkür ederim.
Iyi gunler, admin e ulasmak istiyorum. Contac bilgilerini alabilirmiyim?
Tesekkurler
Selamlar
gmail adresim üzerinden ulasabilirsiniz:
talattufekci@gmail.conm
Merhabalar,
Kendi postgresql bilgilerimizi nereden bulabiliriz? Önceki binance botu projesini de yapmıştım çalıştı. Emeğinize sağlık. Tek kaliteli türkçe kaynak.
Merhabalar,
Jesse ile ilgili merak ettiğim bir şey var. Normalde gerçek zamanlı olduğunda bir timeframe için sadece kapalı olan mumlarla değil aynı zamanda anlık olarak mumun durumuna göre alınan veriler de dikkate alınarak al sat komutları giriyoruz. Jesse ile geriye dönük test yaptığımızda bu durum tam olarak nasıl oluyor? İlgili timeframe’e göre sadece kapanmış mumlar üzerinden işlem yapılıyor şeklinde mi test ediyor yoksa belli saniye aralıklarıyla(örneğin her 10 saniyede 1 şeklinde) gelen verilere göre mumun o anki durumuna bağlı mı?
Paylaşımlarınız için teşekkürler
Merhabalar,
öncelikle emeğinize sağlık, gerçekten çok faydalı bir çalışma / paylaşım oldu.
Mantıken mum içindeki değerlere ulaşılması çok zor çünkü çekilen veri geçmişe ait OHCL (open, high, close,low) verisi.
Benimde merak ettiğim kısım bu şekilde backtest yapmak %100 tutarlılık sağlarmı, 4 saatlik bir mum eğer imbalance mumu ise fiyatın anlık hareketleri canlı ortamda bizi bambaşka noktalara götürür gibi. Bu konuda deneyimlerinizi iletebilirseniz çok sevinirim.
Emeğiniz için çok teşekkürler tekrar 🙂
size nasıl ulaşabilirim