Otomatik Ticaretin Yükselişi: S&P 500'de Ticaret Yapan Makineler

Yayınlanan: 2022-03-11

Günümüzde, farklı varlıklarla (hisse senetleri, endeks vadeli işlemleri, emtialar gibi) alım satım faaliyetlerinin yüzde 60'ından fazlası artık “insan” tüccarlar tarafından yapılmamakta, bunun yerine otomatik ticarete güvenmektedir. Uzun vadede pozitif bir getiri elde etmek amacıyla farklı pazarlarda varlıkları otomatik olarak alıp satan belirli algoritmalara dayalı özel programlar vardır.

Bu makalede, olumlu bir kazanç elde etmek için bir sonraki ticaretin nasıl yapılması gerektiğini iyi bir doğrulukla nasıl tahmin edeceğinizi göstereceğim. Bu örnek için, alım satım yapılacak temel varlık olarak, daha büyük sermayeli 500 ABD şirketinin ağırlıklı ortalaması olan S&P 500 endeksini seçtim. Uygulanması çok basit bir strateji, Wall Street Exchange işlem görmeye başladığında S&P 500 endeksini sabah 9:30'da satın almak ve kapanış seansında Doğu Saati ile 16:00'da satmaktır. Endeksin kapanış fiyatı açılış fiyatından yüksekse pozitif kazanç olurken, kapanış fiyatı açılış fiyatından düşükse negatif kazanç sağlanır. Öyleyse soru şudur: İşlem seansının açılış fiyatından daha yüksek bir kapanış fiyatıyla sonuçlanıp sonuçlanmayacağını nasıl bilebiliriz? Makine Öğrenimi, böylesine karmaşık bir görevi başarmak için güçlü bir araçtır ve ticaret kararlarımızda bizi desteklemek için yararlı bir araç olabilir.

Makine Öğrenimi, birçok faydalı gerçek yaşam uygulamasının yeni sınırıdır. Finansal ticaret bunlardan biridir ve bu sektörde çok sık kullanılmaktadır. Makine Öğrenimi ile ilgili önemli bir kavram, örüntü tanıma gibi her türlü olası kural için kod yazmamıza gerek olmamasıdır. Bunun nedeni, Makine Öğrenimi ile ilişkili her modelin verilerin kendisinden öğrenmesi ve daha sonra görünmeyen yeni verileri tahmin etmek için kullanılabilmesidir.

Sorumluluk Reddi : Bu makalenin amacı, Makine Öğrenimi yöntemlerinin nasıl eğitileceğini göstermektir ve verilen kod örneklerinde her işlev açıklanmamıştır. Bu makale, makalenin kapsamı dışında kalan bazı ayrıntılar eksik olduğundan, bir kişinin tüm kodu kopyalayıp yapıştırmasına ve sağlanan aynı testleri çalıştırmasına izin vermeyi amaçlamamaktadır. Ayrıca, temel Python bilgisi gereklidir. Makalenin temel amacı, finans sektöründeki alım ve satımları tahmin etmede makine öğreniminin nasıl etkili olabileceğine dair bir örnek göstermektir. Ancak gerçek para ile ticaret, para yönetimi ve risk yönetimi gibi birçok başka beceriye sahip olmak demektir. Bu makale “büyük resmin” sadece küçük bir parçası.

İlk Finansal Verilerinizi Otomatik Alım Satım Programınızı Oluşturma

Finansal verileri analiz etmek ve doğru ticareti tahmin etmek için ilk programınızı mı oluşturmak istiyorsunuz? Sana nasıl olduğunu göstereyim. Python for Machine Learning kodunu kullanacağım ve Yahoo Finance hizmetinden geçmiş verileri kullanacağız. Daha önce de belirtildiği gibi, tahminlerimizi yapmadan önce modeli eğitmek için tarihsel veriler gereklidir.

Başlamak için yüklememiz gerekiyor:

  • Python ve özellikle IPython notebook kullanmanızı öneririm.
  • Yahoo Finance Python paketi (tam adı yahoo-finance ) terminal komutu aracılığıyla: pip install yahoo-finance .
  • GraphLab adlı Machine Learning paketinin ücretsiz deneme sürümü. Bu kitaplığın faydalı belgelerini kontrol etmekten çekinmeyin.

GraphLab'ın yalnızca bir bölümünün açık kaynak, SFrame olduğunu unutmayın, bu nedenle kitaplığın tamamını kullanmak için bir lisansa ihtiyacımız var. Öğrenciler veya Kaggle yarışmalarına katılanlar için 30 günlük ücretsiz bir lisans ve ticari olmayan bir lisans vardır. Benim bakış açıma göre, GraphLab Create, verileri analiz etmek ve Makine Öğrenimi modellerini eğitmek için çok sezgisel ve kullanımı kolay bir kitaplıktır.

Python Kodunda Kazma

İnternetten finansal verilerin nasıl indirileceğini görmek için bazı Python kodlarını inceleyelim. Aşağıdaki kodu test etmek için IPython notebook kullanmanızı öneririm, çünkü IPython'un geleneksel bir IDE'ye kıyasla birçok avantajı vardır, özellikle kaynak kodu, yürütme kodunu, tablo verilerini ve grafikleri aynı belge üzerinde birleştirmemiz gerektiğinde. IPython not defterini kullanmak için kısa bir açıklama için lütfen IPython Not Defterine Giriş makalesine bakın.

Şimdi yeni bir IPython not defteri oluşturalım ve S&P 500 endeksinin geçmiş fiyatlarını indirmek için bir kod yazalım. Diğer araçları kullanmayı tercih ederseniz, tercih ettiğiniz IDE'de yeni bir Python projesiyle başlayabileceğinizi unutmayın.

 import graphlab as gl from __future__ import division from datetime import datetime from yahoo_finance import Share # download historical prices of S&P 500 index today = datetime.strftime(datetime.today(), "%Y-%m-%d") stock = Share('^GSPC') # ^GSPC is the Yahoo finance symbol to refer S&P 500 index # we gather historical quotes from 2001-01-01 up to today hist_quotes = stock.get_historical('2001-01-01', today) # here is how a row looks like hist_quotes[0] {'Adj_Close': '2091.580078', 'Close': '2091.580078', 'Date': '2016-04-22', 'High': '2094.320068', 'Low': '2081.199951', 'Open': '2091.48999', 'Symbol': '%5eGSPC', 'Volume': '3790580000'}

Burada hist_quotes , sözlüklerin bir listesidir ve her sözlük nesnesi, Open , High , Low , Close , Adj_close , Volume , Symbol ve Date değerlerine sahip bir işlem günüdür. Her işlem günü boyunca, fiyat genellikle Open fiyatından başlayarak Close fiyatına kadar değişir ve bir maksimum ve bir minimum değeri High ve Low değerlerine ulaşır. Bunu baştan sona okumamız ve en alakalı verilerin her birinin listelerini oluşturmamız gerekiyor. Ayrıca, veriler ilk başta en son değerlere göre sıralanmalıdır, bu nedenle onu tersine çevirmemiz gerekir:

 l_date = [] l_open = [] l_high = [] l_low = [] l_close = [] l_volume = [] # reverse the list hist_quotes.reverse() for quotes in hist_quotes: l_date.append(quotes['Date']) l_open.append(float(quotes['Open'])) l_high.append(float(quotes['High'])) l_low.append(float(quotes['Low'])) l_close.append(float(quotes['Close'])) l_volume.append(int(quotes['Volume']))

İndirilen tüm alıntıları, yüksek düzeyde ölçeklenebilir sütun tabanlı bir veri çerçevesi olan ve sıkıştırılmış bir SFrame nesnesine paketleyebiliriz. Avantajlarından biri de disk destekli olduğu için RAM miktarından daha büyük olabilmesidir. SFrame hakkında daha fazla bilgi edinmek için belgelere göz atabilirsiniz.

Öyleyse, tarihsel verileri depolayalım ve sonra kontrol edelim:

 qq = gl.SFrame({'datetime' : l_date, 'open' : l_open, 'high' : l_high, 'low' : l_low, 'close' : l_close, 'volume' : l_volume}) # datetime is a string, so convert into datetime object qq['datetime'] = qq['datetime'].apply(lambda x:datetime.strptime(x, '%Y-%m-%d')) # just to check if data is sorted in ascending mode qq.head(3)
kapat tarih saat yüksek düşük açık hacim
1283.27 2001-01-02 00:00:00 1320.28 1276.05 1320.28 1129400000
1347.56 2001-01-03 00:00:00 1347.76 1274.62 1283.27 1880700000
1333.34 2001-01-04 00:00:00 1350.24 1329.14 1347.56 2131000000

Artık SFrame yöntemi save ile verileri diske aşağıdaki gibi kaydedebiliriz:

 qq.save(“SP500_daily.bin”) # once data is saved, we can use the following instruction to retrieve it qq = gl.SFrame(“SP500_daily.bin/”)

Bakalım S&P 500 Nasıl Görünüyor?

Yüklenen S&P 500 verilerinin nasıl görüneceğini görmek için aşağıdaki kodu kullanabiliriz:

 import matplotlib.pyplot as plt %matplotlib inline # only for those who are using IPython notebook plt.plot(qq['close'])

Kodun çıktısı aşağıdaki grafiktir:

Yukarıdaki Python kodu tarafından işlendiği gibi, genellikle zamanla büyüyen S&P 500 grafiği.

Bazı Makine Öğrenimi Modellerinin Eğitimi

Sonuç Ekleme

Bu yazının giriş kısmında belirttiğim gibi her modelin amacı kapanış fiyatının açılış fiyatından daha yüksek olup olmayacağını tahmin etmektir. Dolayısıyla, bu durumda, dayanak varlığı satın alırken pozitif bir getiri elde edebiliriz. Bu nedenle, verilerimize target veya predicted değişken olacak bir outcome sütunu eklememiz gerekiyor. Bu yeni sütunun her satırı şöyle olacaktır:

  • Closing fiyatı Opening fiyatından yüksek olan bir Yukarı gün için +1 .
  • -1 Closing fiyatı Opening fiyatından daha düşük olan bir Aşağı gün için.
 # add the outcome variable, 1 if the trading session was positive (close>open), 0 otherwise qq['outcome'] = qq.apply(lambda x: 1 if x['close'] > x['open'] else -1) # we also need to add three new columns 'ho' 'lo' and 'gain' # they will be useful to backtest the model, later qq['ho'] = qq['high'] - qq['open'] # distance between Highest and Opening price qq['lo'] = qq['low'] - qq['open'] # distance between Lowest and Opening price qq['gain'] = qq['close'] - qq['open']

Son işlem gününden birkaç gün önce değerlendirme yapmamız gerektiğinden, verileri bir veya daha fazla gün geciktirmemiz gerekiyor. Bu tür bir gecikme işlemi için, GraphLab paketinden TimeSeries adlı başka bir nesneye ihtiyacımız var. TimeSeries , verileri belirli sayıda satır geride bırakan bir yöntem shift sahiptir.

 ts = gl.TimeSeries(qq, index='datetime') # add the outcome variable, 1 if the bar was positive (close>open), 0 otherwise ts['outcome'] = ts.apply(lambda x: 1 if x['close'] > x['open'] else -1) # GENERATE SOME LAGGED TIMESERIES ts_1 = ts.shift(1) # by 1 day ts_2 = ts.shift(2) # by 2 days # ...etc.... # it's an arbitrary decision how many days of lag are needed to create a good forecaster, so # everyone can experiment by his own decision

Tahminci Ekleme

Tahminciler , modeli eğitmek ve sonucumuzu tahmin etmek için seçilmesi gereken bir dizi özellik değişkenidir . Bu nedenle, tahmin faktörü seçimi, tahmincinin en önemli bileşeni olmasa da çok önemlidir.

Sadece birkaç örnek vermek gerekirse, dikkate alınması gereken bir faktör, bugünün kapanışının dünkü kapanıştan daha yüksek olup olmadığı ve bunun önceki iki günün kapanışıyla uzatılabileceği vb. olabilir. Benzer bir seçim aşağıdaki kodla çevrilebilir:

 ts['feat1'] = ts['close'] > ts_1['close'] ts['feat2'] = ts['close'] > ts_2['close']

Yukarıda gösterildiği gibi, karşılaştırma doğruysa 1 , aksi takdirde 0 içeren veri kümemize ( ts ) feat1 ve feat2 olmak üzere iki yeni özellik sütunu ekledim.

Bu makale, Finans sektörüne uygulanan bir Makine Öğrenimi örneği vermeyi amaçlamaktadır. Makine Öğrenimi modellerinin finansal verilerle nasıl kullanılabileceğine odaklanmayı tercih ediyorum ve modelleri eğitmek için doğru faktörlerin nasıl seçileceğine ilişkin ayrıntılara girmeyeceğiz. Karmaşıklığın önemli ölçüde artması nedeniyle, belirli faktörlerin neden diğerlerine göre kullanıldığını açıklamak çok ayrıntılıdır. Benim iş araştırmam, iyi bir tahmin edici oluşturmak için faktörlerin seçilmesine ilişkin birçok hipotezi incelemektir. Bu nedenle başlangıç ​​olarak, modelin doğruluğunu artırıp artıramayacaklarını görmek için birçok farklı faktör kombinasyonunu denemenizi öneririm.

 # add_features is a helper function, which is out of the scope of this article, # and it returns a tuple with: # ts: a timeseries object with, in addition to the already included columns, also lagged columns # as well as some features added to train the model, as shown above with feat1 and feat2 examples # l_features: a list with all features used to train Classifier models # l_lr_features: a list all features used to train Linear Regression models ts, l_features, l_lr_features = add_features(ts) # add the gain column, for trading operations with LONG only positions. # The gain is the difference between Closing price - Opening price ts['gain'] = ts['close'] - ts['open'] ratio = 0.8 # 80% of training set and 20% of testing set training = ts.to_sframe()[0:round(len(ts)*ratio)] testing = ts.to_sframe()[round(len(ts)*ratio):]

Karar Ağacı Modeli Eğitimi

GraphLab Create, Machine Learning modellerini uygulamak için çok temiz bir arayüze sahiptir. Her modelin, modele bir eğitim veri seti uydurmak için kullanılan bir create yöntemi vardır. Tipik parametreler şunlardır:

  • training - özellik sütunları ve bir hedef sütunu içeren bir eğitim setidir.
  • target - hedef değişkeni içeren sütunun adıdır.
  • validation_set - modelin genelleme performansını izlemek için bir veri kümesidir. Bizim durumumuzda validation_set yok.
  • features - modeli eğitmek için kullanılan özelliklerin sütun adlarının bir listesidir.
  • verbose - true , eğitim sırasında ilerleme bilgilerini yazdırın.

Diğer parametreler modelin kendisine özgüdür, örneğin:

  • max_depth - bir ağacın maksimum derinliğidir.

Aşağıdaki kod ile karar ağacımızı oluşturuyoruz:

 max_tree_depth = 6 decision_tree = gl.decision_tree_classifier.create(training, validation_set=None, target='outcome', features=l_features, max_depth=max_tree_depth, verbose=False)

Takılan Modelin Performansını Ölçme

Doğruluk , tahmincinin iyiliğini değerlendirmek için önemli bir ölçümdür. Toplam veri noktalarının sayısına bölünen doğru tahminlerin sayısıdır. Model eğitim verileriyle donatıldığından, eğitim seti ile değerlendirilen doğruluk, bir test seti ile elde edilenden daha iyidir.

Kesinlik , pozitif olan pozitif tahminlerin oranıdır. "Mükemmel" bir kazanma oranı elde etmek için 1 yakın bir sayı olmak için hassasiyete ihtiyacımız var. GraphLab Create paketinden başka bir sınıflandırıcı olarak decision_tree , uygun modelin birçok önemli metriğini elde etmek için kendi yöntemini evaluate .

Geri çağırma , bir sınıflandırıcının olumlu örnekleri tahmin etme yeteneğini ölçer. Geri çağırma, rastgele seçilen bir pozitif örneğin sınıflandırıcı tarafından doğru olarak tanımlanma olasılığı olarak yorumlanabilir. "Mükemmel" bir kazanma oranı elde etmek için kesinliğin 1 yakın bir sayı olmasına ihtiyacımız var.

Aşağıdaki kod, hem eğitim seti hem de test seti ile takılan modelin doğruluğunu gösterecektir:

 decision_tree.evaluate(training)['accuracy'], decision_tree.evaluate(testing)['accuracy'] (0.6077348066298343, 0.577373211963589)

Yukarıda gösterildiği gibi, test seti ile modelin doğruluğu yaklaşık yüzde 57'dir, bu da bir şekilde yazı tura atmaktan (yüzde 50) daha iyidir.

Verileri Tahmin Etme

GraphLab Create, farklı takılan modellerden verileri tahmin etmek için aynı arayüze sahiptir. Hedef outcome tahmin etmek için bir test setine ihtiyaç duyan predict yöntemini bizim durumumuzda kullanacağız. Şimdi, test setinden verileri tahmin edebiliriz:

 predictions = decision_tree.predict(testing) # and we add the predictions column in testing set testing['predictions'] = predictions # let's see the first 10 predictions, compared to real values (outcome column) testing[['datetime', 'outcome', 'predictions']].head(10)
tarih saat sonuç tahminler
2013-04-05 00:00:00 -1 -1
2013-04-08 00:00:00 1 1
2013-04-09 00:00:00 1 1
2013-04-10 00:00:00 1 -1
2013-04-11 00:00:00 1 -1
2013-04-12 00:00:00 -1 -1
2013-04-15 00:00:00 -1 1
2013-04-16 00:00:00 1 1
2013-04-17 00:00:00 -1 -1
2013-04-18 00:00:00 -1 1

Yanlış pozitifler , modelin pozitif bir sonuç öngördüğü, ancak test setinden elde edilen gerçek sonucun negatif olduğu durumlardır. Tersine, Yanlış negatifler , test setinden elde edilen gerçek sonucun pozitif olduğu durumlarda modelin negatif bir sonuç öngördüğü durumlardır.

Ticaret stratejimiz, S&P 500'ü Opening fiyatından satın almak ve Closing fiyatından satmak için pozitif tahmin edilen bir sonucu bekler, bu nedenle umudumuz kayıpları önlemek için en düşük Yanlış pozitif oranına sahip olmaktır. Başka bir deyişle, modelimizin en yüksek kesinlik oranına sahip olmasını bekliyoruz.

Gördüğümüz gibi, tahmin edilen ilk on değer içinde iki yanlış negatif (2013-04-10 ve 2013-04-11) ve iki yanlış pozitif (2013-04-15 ve 2013-04-18) vardır. test seti.

Basit bir hesaplamayla, bu küçük on tahmin kümesini göz önünde bulundurarak:

  • doğruluk = 6/10 = 0,6 veya %60
  • kesinlik =3/5 = 0,6 veya %60
  • hatırlama = 3/5 = 0,6 veya %60

Genellikle yukarıdaki sayıların birbirinden farklı olduğunu, ancak bu durumda aynı olduklarını unutmayın.

Modeli Geri Test Etme

Şimdi, modelin tahmin edilen değerlerini kullanarak nasıl işlem yapacağını simüle ediyoruz. Tahmin edilen sonuç +1 eşitse, bir Yukarı gün beklediğimiz anlamına gelir. Yukarı gün ile seans başında endeksi alırız ve aynı gün içinde seans sonunda endeksi satarız. Tersine, tahmin edilen sonuç -1 eşitse, bir Aşağı gün bekleriz, bu nedenle o gün boyunca ticaret yapmayacağız.

Bu örnekte, yuvarlak dönüş olarak da adlandırılan eksiksiz bir günlük ticaret için Kar ve Zarar ( pnl ) şu şekilde verilmiştir:

  • pnl = Close - Open (her işlem günü için)

Aşağıda gösterilen kodla, kümülatif kazanç eğrisi (eşitlik eğrisi) ile bir grafik oluşturmak için plot_equity_chart yardımcı fonksiyonunu çağırıyorum. Çok derine inmeden, sadece bir dizi kar ve zarar değeri alır ve çizilecek kümülatif toplamlar dizisini hesaplar.

 pnl = testing[testing['predictions'] == 1]['gain'] # the gain column contains (Close - Open) values # I have written a simple helper function to plot the result of all the trades applied to the # testing set and represent the total return expressed by the index basis points # (not expressed in dollars $) plot_equity_chart(pnl,'Decision tree model') 

Yukarıdaki Python kodu tarafından işlendiği gibi, genellikle yukarı ve sağa giden karar ağacı modeli.

 Mean of PnL is 1.843504 Sharpe is 1.972835 Round turns 511

Burada Sharpe, ticaret modelinin iyiliğinin önemli bir göstergesi olan Yıllık Sharpe oranıdır.

Sharpe oranı, 252'nin kareköküne eşittir, ardından pnl'nin ortalaması ile pnl'nin standart sapması ile çarpılır.

Gün gün ifade edilen işlemler göz önüne alındığında, mean , kar ve zarar listesinin ortalamasıdır ve sd , standart sapmadır. Yukarıda gösterilen formülde basitlik için, 0'a eşit risksiz bir getiri düşündüm.

Ticaret Hakkında Bazı Temel Bilgiler

Endeksin ticareti, doğrudan endeksten türetilen bir varlığın satın alınmasını gerektirir. Birçok broker, S&P 500 endeksini, iki taraf arasında bir sözleşmenin açılış fiyatı ile kapanış fiyatı arasındaki farkı değiştirmek için yapılan bir anlaşma olan CFD (Fark Sözleşmesi) adlı bir türev ürünle çoğaltır.

Örnek : Open 1 CFD S&P 500 satın alın (değer 2000), Günün Close sat (değer 2020). Fark, dolayısıyla kazanç, 20 puandır. Her noktanın değeri 25$ ise:

  • 1 CFD sözleşmesi ile Brüt Kazanç 20 points x $25 = $500 dır.

Diyelim ki komisyoncu kendi geliri için 0,6 puanlık bir kayma tuttu:

  • Net kazanç (20 - 0.6) points x $25 = $485 dır.

Dikkate alınması gereken bir diğer önemli husus, bir ticarette önemli kayıplardan kaçınmaktır. Tahmin edilen sonuç +1 olduğunda ancak gerçek sonuç değeri -1 olduğunda meydana gelebilirler, bu nedenle yanlış bir pozitiftir . Bu durumda, kapanış seansı açılış fiyatından daha düşük bir kapanış fiyatına sahip bir Down gün olur ve bir zarar alırız.

Bir ticarette tahammül edebileceğimiz maksimum kayba karşı koruma sağlamak için bir zararı durdur emri verilmelidir ve böyle bir emir, varlığın fiyatı daha önce belirlediğimiz sabit bir değerin altına düştüğünde tetiklenir.

Bu makalenin başında Yahoo Finance'den indirilen zaman serilerine bakarsak, her gün o gün içinde ulaşılan en düşük fiyat olan Low bir fiyat vardır. Opening fiyatından -3 puan uzakta bir stop seviyesi belirlersek ve Low - Open = -5 stop emri tetiklenir ve açılan pozisyon -5 yerine -3 puan kayıpla kapatılır. Bu riski azaltmak için basit bir yöntemdir. Aşağıdaki kod, durdurma seviyesi olan bir ticareti simüle etmek için yardımcı işlevimi temsil eder:

 # This is a helper function to trade 1 bar (for example 1 day) with a Buy order at opening session # and a Sell order at closing session. To protect against adverse movements of the price, a STOP order # will limit the loss to the stop level (stop parameter must be a negative number) # each bar must contains the following attributes: # Open, High, Low, Close prices as well as gain = Close - Open and lo = Low - Open def trade_with_stop(bar, slippage = 0, stop=None): """ Given a bar, with a gain obtained by the closing price - opening price it applies a stop limit order to limit a negative loss If stop is equal to None, then it returns bar['gain'] """ bar['gain'] = bar['gain'] - slippage if stop<>None: real_stop = stop - slippage if bar['lo']<=stop: return real_stop # stop == None return bar['gain']

Ticaret Maliyetleri

İşlem maliyetleri, menkul kıymetleri alırken veya satarken katlanılan giderlerdir. İşlem maliyetleri, komisyoncu komisyonlarını ve spreadleri (krupiyenin bir menkul kıymet için ödediği fiyat ile alıcının ödediği fiyat arasındaki fark) içerir ve gerçek bir senaryoya benzer şekilde stratejimizi geriye dönük test etmek istiyorsak, bunların dikkate alınması gerekir. Hisse senedi ticaretinde kayma, genellikle spreadde bir değişiklik olduğunda meydana gelir. Bu örnekte ve sonraki devam eden simülasyonlar için ticaret maliyetleri şu şekilde sabitlenmiştir:

  • Kayma = 0,6 puan
  • Komisyon = her işlem için 1$ (bir tur 2$'a mal olacak)

Sadece bazı rakamlar yazmak gerekirse, brüt kazancımız 10 puan, 1 puan = 25$, yani alım satım maliyetleri dahil 250$ olsaydı, net kazancımız (10 - 0.6)*$25 - 2 = $233 olurdu.

Aşağıdaki kod, -3 puanlık stop loss ile önceki ticaret stratejisinin bir simülasyonunu göstermektedir. Mavi eğri, birikimli getirilerin eğrisidir. Hesaplanan tek maliyet kaymadır (0,6 puan) ve sonuç baz puan olarak ifade edilir (Yahoo Finance'ten indirilen S&P 500 değerlerinin aynı temel birimi).

 SLIPPAGE = 0.6 STOP = -3 trades = testing[testing['predictions'] == 1][('datetime', 'gain', 'ho', 'lo', 'open', 'close')] trades['pnl'] = trades.apply(lambda x: trade_with_stop(x, slippage=SLIPPAGE, stop=STOP)) plot_equity_chart(trades['pnl'],'Decision tree model') print("Slippage is %s, STOP level at %s" % (SLIPPAGE, STOP)) 

Karar ağacı modeli, genellikle yukarı ve sağa gidiyor, ancak yukarıdaki Python kodunda gösterildiği gibi daha az belirgin ani artışlarla.

 Mean of PnL is 2.162171 Sharpe is 3.502897 Round turns 511 Slippage is 0.6 STOP level at -3

Aşağıdaki kod, biraz farklı bir şekilde tahmin yapmak için kullanılır. Lütfen output_type = “probability” ek parametresiyle çağrılan predict yöntemine dikkat edin. Bu parametre, sınıf tahminleri yerine tahmin edilen değerlerin olasılıklarını döndürmek için kullanılır (pozitif tahmin edilen bir sonuç için +1 , negatif olarak tahmin edilen bir sonuç için -1 ). 0.5 eşit veya daha büyük bir olasılık, +1 tahmini değeriyle ve 0.5 küçük bir olasılık değeri, -1 tahmini değeriyle ilişkilendirilir. Bu olasılık ne kadar yüksek olursa, gerçek bir Yukarı Günü tahmin etme şansımız o kadar artar.

 predictions_prob = decision_tree.predict(testing, output_type = 'probability') # predictions_prob will contain probabilities instead of the predicted class (-1 or +1)

Şimdi, kayma ve komisyonlar da dahil olmak üzere kümülatif getiri serilerini hesaplayan ve değerlerini backtest_ml_model adlı bir yardımcı fonksiyonla modeli geriye dönük test ediyoruz. Kısaca, backtest_ml_model işlevini tam olarak açıklamadan, vurgulanması gereken önemli ayrıntı, önceki örnekte yaptığımız gibi o günleri tahmini bir outcome = 1 ile filtrelemek yerine, şimdi bu predictions_prob bir threshold = 0.5 eşit veya daha büyük filtreliyoruz, aşağıdaki gibi:

 trades = testing[predictions_prob>=0.5][('datetime', 'gain', 'ho', 'lo', 'open', 'close')]

Her işlem gününün Net kazancının şu olduğunu unutmayın: Net gain = (Gross gain - SLIPPAGE) * MULT - 2 * COMMISSION .

Bir ticaret stratejisinin iyiliğini değerlendirmek için kullanılan bir diğer önemli ölçü, Maksimum Düşüştür . Genel olarak, yatırım yapılan bir portföyün değerinde zirveden dibe doğru en büyük tek düşüşü ölçer. Bizim durumumuzda, öz sermaye eğrisinin tepe noktasından en altına doğru en önemli düşüştür (portföyümüzde sadece bir varlığımız var, S&P 500). Bu nedenle, bir SArray kar ve zarar pnl , düşüşü şu şekilde hesaplarız:

 drawdown = pnl - pnl.cumulative_max() max_drawdown = min(drawdown)

Yardımcı işlevin içinde backtest_summary hesaplanır:

  • Yukarıda gösterildiği gibi maksimum düşüş (dolar cinsinden).
  • Doğruluk, Graphlab.evaluation yöntemiyle.
  • Graphlab.evaluation yöntemiyle kesinlik.
  • Graphlab.evaluation yöntemiyle hatırlayın.

Hepsini bir araya getirirsek, aşağıdaki örnek, model stratejisinin kümülatif getirilerini temsil eden öz sermaye eğrisini gösterir ve tüm değerler dolar cinsinden ifade edilir.

 model = decision_tree predictions_prob = model.predict(testing, output_type="probability") THRESHOLD = 0.5 bt_1_1 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_1) 

Yukarıdaki Python kodu tarafından işlendiği gibi, Y ekseni "dolar" olarak etiketlenmiş ve 30.000'e kadar çıkan ve X ekseni "dönüş sayısı" olarak etiketlenmiş ve 600'e kadar uzanan DecisionTree grafiği. Grafiklendirilmiş verinin kendisi önceki işleme ile aynıdır.

 Mean of PnL is 54.054286 Sharpe is 3.502897 Round turns 511 Name: DecisionTree Accuracy: 0.577373211964 Precision: 0.587084148728 Recall: 0.724637681159 Max Drawdown: -1769.00025

Tahmin edilen değerlerin kesinliğini artırmak için, standart 0.5 (yüzde 50) olasılık yerine daha yüksek bir eşik değeri seçiyoruz ve modelin bir Yukarı gün tahmin ettiğinden daha emin oluyoruz.

 THRESHOLD = 0.55 # it's the minimum threshold to predict an Up day so hopefully a good day to trade bt_1_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_2) 

DecisionTree grafiği, Y ekseni "dolar" olarak etiketlenmiş ve 30.000'e kadar çıkıyor ve X ekseni "dönüş sayısı" olarak etiketlenmiş ve yukarıdaki Python koduyla işlendiği gibi bu sefer sadece 250'ye kadar uzanıyor. Grafiklendirilmiş verilerin kendisi önceki işlemeye benzer, ancak daha da düzleştirilmiştir.

 Mean of PnL is 118.244689 Sharpe is 6.523478 Round turns 234 Name: DecisionTree Accuracy: 0.560468140442 Precision: 0.662393162393 Recall: 0.374396135266 Max Drawdown: -1769.00025

Yukarıdaki grafikte görebileceğimiz gibi, öz sermaye eğrisi daha az yuvarlak dönüşle bile eskisinden çok daha iyi (Sharp 3,5 yerine 6,5'tir).

Bu noktadan sonra, standart bir değerden daha yüksek bir eşiği olan sonraki tüm modelleri ele alacağız.

Lojistik Sınıflandırıcı Eğitimi

Daha önce karar ağacında yaptığımız gibi araştırmamızı bir Lojistik Sınıflandırıcı modeline uygulayabiliriz. GraphLab Create, Logistic Classifier nesnesiyle aynı arayüze sahiptir ve aynı parametre listesiyle modelimizi oluşturmak için create yöntemini çağıracağız. Ayrıca, tahmin edilen sınıf vektörü (olumlu bir sonuç için +1 ve olumsuz bir sonuç için -1 oluşur) yerine olasılık vektörünü tahmin etmeyi tercih ederiz, bu nedenle, daha iyi bir kesinlik elde etmek için 0.5 büyük bir eşiğimiz olur. tahmin.

 model = gl.logistic_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_2_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_2_2) 

LogisticClassifier grafiği, Y ekseni "dolar" olarak etiketlenir ve bu sefer 50.000'e kadar çıkar ve X ekseni "dönüş sayısı" olarak etiketlenir ve yukarıdaki Python kodu tarafından işlendiği gibi şimdi 450'ye kadar uzanır. Grafiklendirilmiş verilerin kendisi, genel eğiliminde önceki işleme benzer.

 Mean of PnL is 112.704215 Sharpe is 6.447859 Round turns 426 Name: LogisticClassifier Accuracy: 0.638491547464 Precision: 0.659624413146 Recall: 0.678743961353 Max Drawdown: -1769.00025

Bu durumda Karar Ağacına çok benzeyen bir özet var. Sonuçta, her iki model de sınıflandırıcıdır, yalnızca bir ikili sonuç sınıfını tahmin ederler ( +1 , -1 ).

Doğrusal Regresyon Modeli Eğitimi

Bu modelin temel farkı, daha önce bahsedildiği gibi ikili sınıflar yerine sürekli değerlerle uğraşmasıdır. Modeli Up günler için +1 ve Down günler için -1 hedef değişkeni ile eğitmemize gerek yok, hedefimiz sürekli bir değişken olmalıdır. Olumlu bir kazanç, yani Açılış fiyatından daha yüksek bir Kapanış fiyatı tahmin etmek istediğimiz için, artık hedef, eğitim setimizin kazanç sütunu olmalıdır. Ayrıca, özellikler listesi, önceki Open , Close vb. gibi sürekli değerlerden oluşmalıdır.

Kısaca, doğru özelliklerin nasıl seçileceğinin ayrıntılarına girmeyeceğim, çünkü bu, bir veri kümesi üzerinde farklı Makine Öğrenimi modellerini nasıl uygulamamız gerektiğini göstermeye daha meyilli olan bu makalenin kapsamı dışındadır. Create yöntemine iletilen parametrelerin listesi şunlardır:

  • training - özellik sütunları ve bir hedef sütunu içeren bir eğitim setidir.
  • target - hedef değişkeni içeren sütunun adıdır.
  • validation_set - modelin genelleme performansını izlemek için bir veri kümesidir. Bizim durumumuzda validation_set yok.
  • features - modeli eğitmek için kullanılan özelliklerin sütun adlarının bir listesidir, bu model için Sınıflandırıcı modellerine göre başka bir küme kullanacağız.
  • verbose - true ise, eğitim sırasında ilerleme bilgilerini yazdırır.
  • max_iterations - verilerde izin verilen maksimum geçiş sayısıdır. Veriler üzerinden daha fazla geçiş, daha doğru bir şekilde eğitilmiş bir modelle sonuçlanabilir.
 model = gl.linear_regression.create(training, target='gain', features = l_lr_features, validation_set=None, verbose=False, max_iterations=100) predictions = model.predict(testing) # a linear regression model, predict continuous values, so we need to make an estimation of their # probabilities of success and normalize all values in order to have a vector of probabilities predictions_max, predictions_min = max(predictions), min(predictions) predictions_prob = (predictions - predictions_min)/(predictions_max - predictions_min)

Şimdiye kadar, tahmin edilen kazançların SArray olan tahminlerimiz varken, predictions_prob , predictions değerleri normalleştirilmiş SArray . İyi bir doğruluk ve belirli sayıda yuvarlak dönüş elde etmek için önceki modellerle karşılaştırılabilir bir eşik değeri seçtim 0.4 . 0.4 küçük bir predictions_prob için, bir Aşağı gün beklendiği için backtest_linear_model yardımcı işlevi bir işlem açmaz. Aksi takdirde, bir ticaret açılacaktır.

 THRESHOLD = 0.4 bt_3_2 = backtest_linear_model(testing, predictions_prob, target='gain', threshold=THRESHOLD, STOP = -3, plot_title=model.name()) backtest_summary(bt_3_2) 

Yukarıdaki Python kodu tarafından işlendiği gibi, Y ekseni "dolar" olarak etiketlenmiş ve 45.000'e kadar çıkan ve X ekseni "dönüş sayısı" etiketli ve 350'ye kadar uzanan LinearRegression grafiği. Grafiği çizilen verilerin kendisi yine benzerdir, ancak önceki işleme ile tam olarak aynı değildir.

 Mean of PnL is 138.868280 Sharpe is 7.650187 Round turns 319 Name: LinearRegression Accuracy: 0.631989596879 Precision: 0.705329153605 Recall: 0.54347826087 Max Drawdown: -1769.00025

Güçlendirilmiş Ağaç Eğitimi

Daha önce bir karar ağacını eğittiğimiz gibi, şimdi diğer sınıflandırıcı modelleri için kullanılan aynı parametrelerle güçlendirilmiş bir ağaç sınıflandırıcıyı eğiteceğiz. Ek olarak, artırma için maksimum yineleme sayısını artırmak için max_iterations = 12 olarak ayarladık. Her yineleme, fazladan bir ağacın oluşturulmasıyla sonuçlanır. Ayrıca hassasiyeti artırmak için 0.5 daha yüksek bir eşik değeri belirledik.

 model = gl.boosted_trees_classifier.create(training, target='outcome', features=l_features, validation_set=None, max_iterations=12, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.7 bt_4_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_4_2) 

BoostedTreesClassifier grafiği, Y ekseni "dolar" olarak etiketlenir ve 25.000'e kadar çıkar ve X ekseni "yuvarlak dönüş sayısı" olarak etiketlenir ve yukarıdaki Python koduyla işlendiği gibi 250'ye kadar uzanır. Grafiğe alınan verilerin kendisi, X ekseninde 175 civarında daha keskin bir artışla yine önceki işlemeye benzer.

 Mean of PnL is 112.002338 Sharpe is 6.341981 Round turns 214 Name: BoostedTreesClassifier Accuracy: 0.563068920676 Precision: 0.682242990654 Recall: 0.352657004831 Max Drawdown: -1769.00025

Rastgele Orman Eğitimi

Bu bizim son eğitilmiş modelimizdir, bir karar ağaçları topluluğu tarafından oluşturulan bir Rastgele Orman Sınıflandırıcısı. Modelde kullanılacak maksimum ağaç sayısı, çok fazla karmaşıklığı ve fazla uydurmayı önlemek için num_trees = 10 olarak ayarlanmıştır.

 model = gl.random_forest_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False, num_trees = 10) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_5_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_5_2) 

RandomForestClassifier grafiği, Y ekseni "dolar" olarak etiketlenir ve 40.000'e kadar çıkar ve X ekseni "dönüş sayısı" olarak etiketlenir ve yukarıdaki Python koduyla işlendiği gibi 350'ye kadar uzanır. Grafiklendirilmiş verilerin kendisi yine önceki işlemeye benzer.

 Mean of PnL is 114.786962 sharpe is 6.384243 Round turns 311 Name: RandomForestClassifier Accuracy: 0.598179453836 Precision: 0.668810289389 Recall: 0.502415458937 Max Drawdown: -1769.00025

Collecting All the Models Together

Now we can join all the strategies together and see the overall result. It's interesting to see the summary of all Machine Learning models, sorted by their precision.

name accuracy precision round turns sharpe
LinearRegression 0.63 0.71 319 7.65
BoostedTreesClassifier 0,56 0.68 214 6.34
RandomForestClassifier 0.60 0.67 311 6.38
DecisionTree 0,56 0.66 234 6.52
LogisticClassifier 0.64 0.66 426 6.45

If we collect all the profit and loss for each one of the previous models in the array pnl , the following chart depicts the equity curve obtained by the sum of each profit and loss, day by day.

 Mean of PnL is 119.446463 Sharpe is 6.685744 Round turns 1504 First trading day 2013-04-09 Last trading day 2016-04-22 Total return 179647

Just to give some numbers, with about 3 years of trading, all models have a total gain of about 180,000 dollars. The maximum exposition is 5 CFD contracts in the market, but to reduce the risk they all are closed at the end of each day, so overnight positions are not allowed.

Statistics of the Aggregation of All Models Together

Since each model can open a trade, but we added 5 concurrent models together, during the same day there could be from 1 contract up to 5 CFD contracts. If all models agree to open trades during the same day, there is a high chance to have an Up day predicted. Moreover, we can group by the number of models that open a trade at the same time during the opening session of the day. Then we evaluate precision as a function of the number of concurrent models.

As we can see by the chart depicted above, the precision gets better as the number of models do agree to open a trade. The more models agree, the more precision we get. For instance, with 5 models triggered the same day, the chance to predict an Up day is greater than 85%.

Çözüm

Even in the financial world, Machine Learning is welcomed as a powerful instrument to learn from data and give us great forecasting tools. Each model shows different values of accuracy and precision, but in general, all models can be aggregated to achieve a better result than each one of them taken singularly. GraphLab Create is a great library, easy to use, scalable and able to manage Big Data very quickly. It implements different scientific and forecasting models, and there is a free license for students and Kaggle competitions.

İlgili: Makine Öğrenimi Teorisine Giriş ve Uygulamaları: Örneklerle Görsel Bir Eğitim

Additional disclosure: This article has been prepared solely for information purposes, and is not an offer to buy or sell or a solicitation of an offer to buy or sell any security or instrument or to participate in any particular trading strategy. Examples presented on these sites are for educational purposes only. Past results are not necessarily indicative of future results.