डेटा-ड्राइव तकनीक के आधार पर संबद्ध लेनदेन

लेखक:अच्छाई, बनाया गयाः 2019-08-21 13:50:23, अद्यतन किया गयाः 2023-10-19 21:01:31

img

जोड़े व्यापार एक अच्छा उदाहरण है जोड़े व्यापार रणनीतियों के निर्माण के लिए गणितीय विश्लेषण पर आधारित है। इस लेख में, हम दिखाएंगे कि कैसे डेटा का उपयोग करके जोड़े व्यापार रणनीतियों को बनाने और स्वचालित करने के लिए।

मूल सिद्धांत

假设你有一对投资标的X和Y具有一些潜在的关联,例如两家公司生产相同的产品,如百事可乐和可口可乐。你希望这两者的价格比率或基差(也称为差价)随时间的变化而保持不变。然而,由于临时供需变化,如一个投资标的的大买/卖订单,对其中一家公司的重要新闻的反应等,这两对之间的价差可能会不时出现分歧。在这种情况下,一只投资标的向上移动而另一只投资标的相对于彼此向下移动。如果你希望这种分歧随着时间的推移恢复正常,你就可以发现交易机会(或套利机会)。此种套利机会在数字货币市场或者国内商品期货市场比比皆是,比如BTC与避险资产的关系;期货中豆粕,豆油与大豆品种之间的关系.

जब एक अस्थायी मूल्य अंतर होता है, तो आप एक अच्छा प्रदर्शन करने वाले निवेशक को बेच देंगे और एक खराब प्रदर्शन करने वाले निवेशक को खरीद लेंगे। आप आश्वस्त हैं कि दो निवेशकों के बीच की अंतर अंततः एक अच्छा प्रदर्शन करने वाले निवेशक के पतन या खराब प्रदर्शन करने वाले निवेशक के पुनरुत्थान या दोनों के माध्यम से होगा। आपके ट्रेडों को इन सभी समान परिदृश्यों में पैसा मिलेगा। यदि निवेशक एक बार ऊपर या नीचे चले जाते हैं और उनके बीच का अंतर नहीं बदलते हैं, तो आप न तो पैसा बनाते हैं और न ही नुकसान करते हैं।

इस प्रकार, जोड़ा व्यापार एक बाजार-तटस्थ ट्रेडिंग रणनीति है जो व्यापारियों को लगभग किसी भी बाजार की स्थिति से लाभान्वित करने में सक्षम बनाती हैः ऊपर की ओर, नीचे की ओर या क्षैतिज रूप से।

अवधारणा की व्याख्याः दो अनुमानित निवेश के संकेत

  • हमारे शोध वातावरण को एक आविष्कारक क्वांटिफाइड प्लेटफॉर्म पर बनाएं

सबसे पहले, काम को सुचारू रूप से करने के लिए, हमें अपने अनुसंधान वातावरण का निर्माण करने की आवश्यकता है, और इस लेख में हम आविष्कारक क्वांटिफाइंग प्लेटफॉर्म का उपयोग करते हैं।FMZ.COM) अनुसंधान वातावरण के निर्माण के लिए, मुख्य रूप से एक सुविधाजनक और तेज़ एपीआई इंटरफ़ेस और एक पूर्ण Docker प्रणाली के बाद के उपयोग के लिए।

आविष्कारकों के लिए क्वांटिफाइड प्लेटफॉर्म के आधिकारिक नाम में, इस डॉकर सिस्टम को होस्टिंग सिस्टम कहा जाता है।

यह एक बहुत ही दिलचस्प और उपयोगी लेख है, लेकिन यह एक बहुत ही दिलचस्प लेख है, और यह एक बहुत ही उपयोगी लेख है।https://www.fmz.com/bbs-topic/4140

जो लोग अपने स्वयं के क्लाउड सर्वर परिनियोजन प्रबंधक खरीदना चाहते हैं, वे इस लेख को देख सकते हैंःhttps://www.fmz.com/bbs-topic/2848

एक बार जब हम एक अच्छी क्लाउड सेवा और व्यवस्थापक प्रणाली को सफलतापूर्वक तैनात कर लेते हैं, तो अब हम पायथन के सबसे बड़े मंदिर को स्थापित करते हैं: एनाकोंडा।

सभी संबंधित प्रोग्रामिंग वातावरणों (निर्भरता पुस्तकालय, संस्करण प्रबंधन, आदि) को लागू करने के लिए सबसे आसान तरीका Anaconda का उपयोग करना है; यह एक पैक किया गया पायथन डेटा विज्ञान पारिस्थितिकी तंत्र और निर्भरता पुस्तकालय प्रबंधक है।

Anaconda को स्थापित करने के तरीके के लिए, कृपया Anaconda के आधिकारिक गाइड देखेंःhttps://www.anaconda.com/distribution/

本文还将用到numpy和pandas这两个目前在Python科学计算方面十分流行且重要的库.

इन मूलभूत कार्यों का संदर्भ मेरे पिछले लेख से लिया जा सकता है, जिसमें मैं Anaconda वातावरण और दो पुस्तकालयों, numpy और pandas को स्थापित करने के बारे में बताया गया था।https://www.fmz.com/digest-topic/4169

अब, चलो कोड के साथ एक "दो अनुमानित निवेश के लिए" लागू करते हैं।

import numpy as np
import pandas as pd

import statsmodels
from statsmodels.tsa.stattools import coint
# just set the seed for the random number generator
np.random.seed(107)

import matplotlib.pyplot as plt

ठीक है, हम यह भी एक बहुत ही प्रसिद्ध पायथन में चार्ट लाइब्रेरी का उपयोग कर रहे हैं matplotlib.

आइए हम एक अनुमानित निवेश सूचक का X उत्पन्न करें और उसके दैनिक रिटर्न को एक सामान्य वितरण के माध्यम से अनुकरण करें। फिर हम दैनिक X मूल्य प्राप्त करने के लिए संचयी जोड़ करते हैं।

# Generate daily returns
Xreturns = np.random.normal(0, 1, 100) 
# sum them and shift all the prices up
X = pd.Series(np.cumsum(
    Xreturns), name='X') 
    + 50
X.plot(figsize=(15,7))
plt.show()

img

एक निवेश के लिए एक्स, एक सामान्य वितरण के माध्यम से उसके दैनिक रिटर्न का अनुकरण करना

अब हमने Y और X को उत्पन्न किया है जो एक दूसरे के साथ बहुत मजबूत संबंध रखते हैं, इसलिए Y का मूल्य X के परिवर्तन के समान होना चाहिए। हम इसे X लेकर, इसे ऊपर ले जाकर और कुछ यादृच्छिक शोर को जोड़कर मॉडलिंग करते हैं जो सामान्य वितरण से निकाले जाते हैं।

noise = np.random.normal(0, 1, 100)
Y = X + 5 + noise
Y.name = 'Y'
pd.concat([X, Y], axis=1).plot(figsize=(15,7))
plt.show()

img

एक्स और वाई के लिए एक साथ निवेश के संकेत

सामंजस्य

协整非常类似于相关性,意味着两个数据系列之间的比率将在平均值附近变化.Y和X这两个系列遵循以下内容:

Y = X + e

जहां y निरंतर अनुपात है, और e शोर है।

दो समय अनुक्रमों के बीच लेन-देन के लिए, यह अनुपात समय के साथ अपेक्षित मानों के लिए समान होना चाहिए, यानी वे सहसंयोजक होने चाहिए। हमने ऊपर जो समय अनुक्रम बनाया है, वह सहसंयोजक है। हम अब दोनों के बीच अनुपात को चित्रित करेंगे ताकि हम देख सकें कि यह कैसा दिखता है।

(Y/X).plot(figsize=(15,7)) 
plt.axhline((Y/X).mean(), color='red', linestyle='--') 
plt.xlabel('Time')
plt.legend(['Price Ratio', 'Mean'])
plt.show()

img

दो सहसंयोजक निवेश संकेतकों के मूल्य के बीच अनुपात और औसत

एक साथ परीक्षण

एक आसान परीक्षण का तरीका है statsmodels.tsa.stattools का उपयोग करना. हम एक बहुत कम पी-वैल्यू देखेंगे क्योंकि हमने दो डेटा श्रृंखलाएं बनाई हैं जो कृत्रिम रूप से यथासंभव एक साथ हैं।

# compute the p-value of the cointegration test
# will inform us as to whether the ratio between the 2 timeseries is stationary
# around its mean
score, pvalue, _ = coint(X,Y)
print pvalue

परिणामः 1.81864477307e-17

ध्यान देंः प्रासंगिकता और सामंजस्य

रिलेटेड और कोऑर्डिनेटेड, हालांकि सैद्धांतिक रूप से समान हैं, लेकिन वे समान नहीं हैं. आइए संबंधित लेकिन कोऑर्डिनेटेड नहीं डेटा श्रृंखलाओं के उदाहरणों को देखें, और इसके विपरीत। सबसे पहले, आइए हमारे द्वारा उत्पन्न श्रृंखलाओं के संबंध की जांच करें।

X.corr(Y)

परिणाम हैः 0.951

जैसा कि हम उम्मीद करते हैं, यह बहुत अधिक है. लेकिन दो संबंधित लेकिन असंगत श्रृंखलाओं के बारे में क्या? एक सरल उदाहरण दो विचलित डेटा श्रृंखलाएं हैं.

ret1 = np.random.normal(1, 1, 100)
ret2 = np.random.normal(2, 1, 100)

s1 = pd.Series( np.cumsum(ret1), name='X')
s2 = pd.Series( np.cumsum(ret2), name='Y')

pd.concat([s1, s2], axis=1 ).plot(figsize=(15,7))
plt.show()
print 'Correlation: ' + str(X_diverging.corr(Y_diverging))
score, pvalue, _ = coint(X_diverging,Y_diverging)
print 'Cointegration test p-value: ' + str(pvalue)

img

दो संबंधित श्रृंखलाएँ (संयुक्त नहीं)

संबंधित गुणांकः 0.998 सहसंयोजक परीक्षण पी मानः 0.258

बिना संबंध के सहसंयोजन के सरल उदाहरण सामान्य वितरण अनुक्रम और वर्ग तरंग हैं।

Y2 = pd.Series(np.random.normal(0, 1, 800), name='Y2') + 20
Y3 = Y2.copy()
Y3[0:100] = 30
Y3[100:200] = 10
Y3[200:300] = 30
Y3[300:400] = 10
Y3[400:500] = 30
Y3[500:600] = 10
Y3[600:700] = 30
Y3[700:800] = 10
Y2.plot(figsize=(15,7))
Y3.plot()
plt.ylim([0, 40])
plt.show()
# correlation is nearly zero
print 'Correlation: ' + str(Y2.corr(Y3))
score, pvalue, _ = coint(Y2,Y3)
print 'Cointegration test p-value: ' + str(pvalue)

img

प्रासंगिकताः 0.007546 सहसंयोजक परीक्षण पी मानः 0.0

यह बहुत कम है, लेकिन पी-वैल्यू ने सही सहयोग दिखाया है!

कैसे एक जोड़ी के लिए सौदा?

चूंकि दो समन्वित समय अनुक्रम (जैसे ऊपर दिए गए X और Y) एक दूसरे के समानांतर और एक दूसरे से भिन्न होते हैं, इसलिए कभी-कभी उच्च और निम्न सीमाएं होती हैं। हम एक निवेशक को खरीदकर और दूसरे को बेचकर एक जोड़ी व्यापार करते हैं। इस प्रकार, यदि दोनों निवेशक एक साथ गिरते हैं या बढ़ते हैं, तो हम न तो पैसा कमाते हैं और न ही खोते हैं, यानी हम बाजार में तटस्थ हैं।

ऊपर Y = X + e में X और Y पर वापस, और अनुपात ((Y / X) को इसके औसत मूल्य के चारों ओर ले जाने के लिए, हम औसत मूल्य पर लौटने के अनुपात के माध्यम से पैसा बनाते हैं। ऐसा करने के लिए, हम ध्यान देंगे कि जब X और Y बहुत दूर होते हैं, तो थ्रेशोल्ड बहुत अधिक या बहुत कम होता हैः

  • बहुआयामी करनाः यह तब होता है जब अनुपात बहुत छोटा होता है और हम इसे बड़ा होने की उम्मीद करते हैं। ऊपर दिए गए उदाहरण में, हम अधिक Y करके और खाली X करके व्यापार करते हैं।

  • खाली करने का अनुपातः यह तब होता है जब अनुपात बहुत बड़ा होता है और हम इसे घंटों में बदलने की उम्मीद करते हैं। ऊपर दिए गए उदाहरण में, हम खाली Y करके और अधिक X करके ट्रेड खोलते हैं।

ध्यान दें कि हमारे पास हमेशा एक हेजिंग हेजिंग स्थिति होती हैः अगर ट्रेडिंग सूचकांक का खरीद-हानि मूल्य होता है, तो खाली हेजिंग स्थिति पैसे कमाएगी, और इसके विपरीत, इसलिए हम समग्र बाजार आंदोलनों के प्रति प्रतिरक्षा रखते हैं।

यदि एक्स और वाई एक दूसरे के सापेक्ष चलते हैं, तो हम पैसा कमाते हैं या नुकसान करते हैं।

डेटा का उपयोग करके समान व्यवहार करने वाले लेन-देन के संकेतों का पता लगाएं

ऐसा करने का सबसे अच्छा तरीका यह है कि आप संदिग्ध लेन-देन के संकेतकों से शुरू करें और एक सांख्यिकीय परीक्षण करें।कई तुलनात्मक विचलनइस तरह की घटनाओं में कई लोग मारे गए हैं।

कई तुलनात्मक विचलनयह एक ऐसी स्थिति है जब कई परीक्षणों को चलाने पर महत्वपूर्ण पी-मूल्यों को गलत तरीके से उत्पन्न करने की संभावना बढ़ जाती है, क्योंकि हमें बहुत सारे परीक्षण चलाने की आवश्यकता होती है। यदि 100 बार यादृच्छिक डेटा पर परीक्षण किया जाता है, तो हमें 0.05 से कम के 5 पी-मूल्यों को देखना चाहिए। यदि आप एक पूरे के लिए n लेन-देन के संकेतकों की तुलना करने जा रहे हैं, तो आप कई गलत पी-मूल्यों को देखेंगे, जो आपके परीक्षण के नमूने में वृद्धि के साथ बढ़ते हैं। इस स्थिति से बचने के लिए, कुछ लेन-देन जोड़े चुनें जिनके लिए आपको यकीन है कि वे सहकार्य कर सकते हैं, और फिर उन्हें अलग से परीक्षण करें। यह काफी कम हो जाएगा।कई तुलनात्मक विचलन

इसलिए, आइए कुछ ट्रेडों को खोजने का प्रयास करें जो सह-अस्तित्व का प्रदर्शन करते हैं। आइए स्टैंडर्ड 500 सूचकांक में बड़े अमेरिकी प्रौद्योगिकी शेयरों की एक टोकरी का उदाहरण लें, जो समान बाजार खंडों में संचालित होते हैं और सह-अस्तित्व की कीमत रखते हैं। हम ट्रेडों की सूची को स्कैन करते हैं और सभी जोड़े के बीच सह-अस्तित्व का परीक्षण करते हैं।

जोड़े गए सभी p-value के लिए, p-value matrix और p-value 0.05 से कम के लिए, सभी जोड़ों को वापस किया गया है।इस तरह के तरीकों में कई बार तुलनात्मक विचलन होने की संभावना होती है, इसलिए उन्हें वास्तव में दूसरी बार सत्यापित करने की आवश्यकता होती है।इस लेख में, हमारी व्याख्याओं की सुविधा के लिए, हम उदाहरणों में इसे नजरअंदाज करने का विकल्प चुनते हैं।

def find_cointegrated_pairs(data):
    n = data.shape[1]
    score_matrix = np.zeros((n, n))
    pvalue_matrix = np.ones((n, n))
    keys = data.keys()
    pairs = []
    for i in range(n):
        for j in range(i+1, n):
            S1 = data[keys[i]]
            S2 = data[keys[j]]
            result = coint(S1, S2)
            score = result[0]
            pvalue = result[1]
            score_matrix[i, j] = score
            pvalue_matrix[i, j] = pvalue
            if pvalue < 0.02:
                pairs.append((keys[i], keys[j]))
    return score_matrix, pvalue_matrix, pairs

ध्यान देंः हमने डेटा में बाजार के बेन्चमार्क (SPX) को शामिल किया है - बाजार कई ट्रेडिंग इंडेक्स के प्रवाह को चलाता है, और आमतौर पर आप दो ऐसा दिखने वाले ट्रेडिंग इंडेक्स पा सकते हैं जो सहसंयोजक हैं; लेकिन वास्तव में वे एक दूसरे के साथ नहीं बल्कि बाजार के साथ सहसंयोजक हैं। इसे मिश्रित चर कहा जाता है। आपके द्वारा पाए गए किसी भी संबंध में बाजार की भागीदारी की जांच करना महत्वपूर्ण है।

from backtester.dataSource.yahoo_data_source import YahooStockDataSource
from datetime import datetime
startDateStr = '2007/12/01'
endDateStr = '2017/12/01'
cachedFolderName = 'yahooData/'
dataSetId = 'testPairsTrading'
instrumentIds = ['SPY','AAPL','ADBE','SYMC','EBAY','MSFT','QCOM',
                 'HPQ','JNPR','AMD','IBM']
ds = YahooStockDataSource(cachedFolderName=cachedFolderName,
                            dataSetId=dataSetId,
                            instrumentIds=instrumentIds,
                            startDateStr=startDateStr,
                            endDateStr=endDateStr,
                            event='history')
data = ds.getBookDataByFeature()['Adj Close']
data.head(3)

img

अब हम कोशिश करते हैं कि हम अपने तरीके का उपयोग करके सहसंयोजक लेनदेन जोड़ों को खोजने का प्रयास करें।

# Heatmap to show the p-values of the cointegration test
# between each pair of stocks
scores, pvalues, pairs = find_cointegrated_pairs(data)
import seaborn
m = [0,0.2,0.4,0.6,0.8,1]
seaborn.heatmap(pvalues, xticklabels=instrumentIds, 
                yticklabels=instrumentIds, cmap=’RdYlGn_r’, 
                mask = (pvalues >= 0.98))
plt.show()
print pairs
[('ADBE', 'MSFT')]

img

ऐसा लगता है कि एडीबीई और एमएसएफटी एसिड एक साथ काम करते हैं। आइए कीमतों को देखें ताकि यह सुनिश्चित हो सके कि यह वास्तव में मायने रखता है।

S1 = data['ADBE']
S2 = data['MSFT']
score, pvalue, _ = coint(S1, S2)
print(pvalue)
ratios = S1 / S2
ratios.plot()
plt.axhline(ratios.mean())
plt.legend([' Ratio'])
plt.show()

img

MSFT और ADBE के बीच मूल्य अनुपात 2008 - 2017

यह अनुपात वास्तव में एक स्थिर औसत की तरह दिखता है. निरपेक्ष अनुपात सांख्यिकीय रूप से बहुत उपयोगी नहीं है. इसे एक z स्कोर के रूप में मानकीकृत करके हमारे संकेतों को और अधिक मददगार बनाता है. Z स्कोर को परिभाषित किया गया हैः

Z स्कोर (मूल्य) = (मूल्य औसत) / मानक विचलन

चेतावनी

वास्तव में, हम आमतौर पर डेटा के लिए कुछ विस्तार करने का प्रयास करते हैं, लेकिन यह मानते हुए कि ये डेटा एक सामान्य वितरण है। हालांकि, कई वित्तीय डेटा एक सामान्य वितरण नहीं हैं, इसलिए हमें बहुत सावधान रहना चाहिए कि हम सांख्यिकीय डेटा उत्पन्न करते समय केवल सामान्य या किसी विशेष वितरण को मान न लें। अनुपातों के वास्तविक वितरण में एक मोटाई का प्रभाव हो सकता है, और जो डेटा चरम पर झुकाव रखते हैं, वे हमारे मॉडल को भ्रमित कर सकते हैं और भारी नुकसान का कारण बन सकते हैं।

def zscore(series):
    return (series - series.mean()) / np.std(series)
zscore(ratios).plot()
plt.axhline(zscore(ratios).mean())
plt.axhline(1.0, color=’red’)
plt.axhline(-1.0, color=’green’)
plt.show()

img

2008-2017 के बीच MSFT और ADBE के बीच Z मूल्य अनुपात

अब अनुपात को औसत के करीब ले जाने के लिए देखना आसान हो गया है, लेकिन कभी-कभी औसत से बड़ा अंतर होना आसान हो जाता है, और हम इसका लाभ उठा सकते हैं।

अब जब हमने एक जोड़े की ट्रेडिंग रणनीति के मूल सिद्धांतों पर चर्चा कर ली है और ऐतिहासिक कीमतों के आधार पर एक साथ एकीकृत ट्रेडिंग इंडेक्स निर्धारित किया है, तो आइए एक ट्रेडिंग सिग्नल विकसित करने का प्रयास करें। सबसे पहले, आइए डेटा तकनीक का उपयोग करके ट्रेडिंग सिग्नल विकसित करने के चरणों को देखेंः

  • विश्वसनीय डेटा एकत्र करना और डेटा को साफ करना

  • डेटा से ट्रेडिंग सिग्नल/लॉजिक को पहचानने के लिए सुविधाएँ बनाना

  • एक फ़ंक्शन चलती औसत या मूल्य डेटा, प्रासंगिकता या अधिक जटिल संकेतों का अनुपात हो सकता है - इनका संयोजन करके नए फ़ंक्शन बनाएँ

  • इन सुविधाओं का उपयोग ट्रेडिंग सिग्नल उत्पन्न करने के लिए किया जाता है, जो कि खरीदने, बेचने या खाली स्थिति देखने के संकेत हैं

सौभाग्य से, हमारे पास एक आविष्कारक क्वांटिफाइंग प्लेटफॉर्म है।fmz.comऔर यह रणनीति डेवलपर्स के लिए एक बड़ी खुशखबरी है कि हम रणनीति तर्क के डिजाइन और कार्यक्षमता के विस्तार में अपनी ऊर्जा और समय खर्च कर सकते हैं।

इन्वेंटर्स क्वांटिफाइड प्लेटफॉर्म पर, जहां कई मुख्यधारा के एक्सचेंजों के इंटरफेस हैं, हमें बस इन एपीआई को कॉल करना है, और बाकी अंतर्निहित लॉजिक को लागू करना है, और एक पेशेवर टीम पहले से ही इसे परिष्कृत कर रही है।

तर्क की पूर्णता के लिए और सिद्धांतों की व्याख्या के लिए, हम यहां इन अंतर्निहित तर्कों को एक तरह से पेश करेंगे, लेकिन वास्तविक संचालन में, पाठक सीधे आविष्कारक द्वारा क्वांटिफाइड एपीआई इंटरफेस को कॉल कर सकते हैं।

तो चलिए शुरू करते हैंः

पहला कदमः अपनी समस्या सेट करें

यहाँ, हम एक संकेत बनाने की कोशिश कर रहे हैं जो हमें बताता है कि अगले क्षण में यह अनुपात खरीद रहा है या बेच रहा है, यानी हमारे पूर्वानुमान चर Y:

Y = अनुपात खरीद (1) या बिक्री (-1) है

Y(t)= Sign(Ratio(t+1) Ratio(t))

ध्यान दें कि हमें वास्तविक लेनदेन के मूल्य का अनुमान लगाने की आवश्यकता नहीं है, और न ही हम अनुपात के वास्तविक मूल्य का अनुमान लगाने की आवश्यकता है (हालांकि हम कर सकते हैं) केवल अगले अनुपात की दिशा का अनुमान लगाने की आवश्यकता है

चरण 2: विश्वसनीय और सटीक डेटा एकत्र करें

आविष्कारक क्वांटिफ़िकेशन आपका दोस्त है! आप बस उस ट्रेडिंग टोकन को निर्दिष्ट करें जिसे आप व्यापार करना चाहते हैं और उस डेटा स्रोत का उपयोग करना चाहते हैं, यह आवश्यक डेटा निकालेगा और लाभांश और ट्रेडिंग टोकन के विभाजन के लिए इसे साफ कर देगा। इसलिए हम यहां डेटा को साफ कर रहे हैं।

हमने पिछले 10 वर्षों (लगभग 2500 डेटा बिंदुओं) के लिए ट्रेडिंग दिनों के लिए निम्नलिखित डेटा प्राप्त किया है, जो कि याहू फाइनेंस का उपयोग करके प्राप्त किया गया हैः शुरुआती मूल्य, समापन मूल्य, उच्चतम मूल्य, निम्नतम मूल्य और ट्रेडिंग मात्रा

तीसरा कदमः डेटा को विभाजित करें

मॉडल की सटीकता का परीक्षण करने के लिए इस बहुत ही महत्वपूर्ण कदम को मत भूलना. हम निम्नलिखित डेटा का उपयोग कर प्रशिक्षण / सत्यापन / परीक्षण विभाजन कर रहे हैं

  • प्रशिक्षण 7 वर्ष ~ 70%

  • परीक्षण ~ 3 वर्ष 30%

ratios = data['ADBE'] / data['MSFT']
print(len(ratios))
train = ratios[:1762]
test = ratios[1762:]

आदर्श रूप से, हमें भी सत्यापन सेट बनाना चाहिए, लेकिन हम अभी ऐसा नहीं करेंगे।

चौथा कदमः विशेषता निर्माण

हम अनुपात में बदलाव की दिशा का पूर्वानुमान लगाना चाहते हैं. हमने देखा है कि हमारे दो ट्रेड मार्कर सहसंयोजक हैं, इसलिए यह अनुपात अक्सर स्थानांतरित हो जाता है और औसत पर वापस आ जाता है. ऐसा लगता है कि हमारी विशेषता अनुपात औसत के कुछ माप होनी चाहिए, वर्तमान मूल्य और औसत के बीच का अंतर हमारे व्यापार संकेतों का उत्पादन कर सकता है।

हम निम्नलिखित सुविधाओं का उपयोग करते हैंः

  • 60 दिन का चलती औसत अनुपातः चलती औसत का माप

  • 5 दिन का चलती औसत अनुपातः औसत के वर्तमान मूल्य का माप

  • 60 दिन का मानक अंतर

  • z स्कोरः ((5d MA - 60d MA) / 60d SD

ratios_mavg5 = train.rolling(window=5,
                               center=False).mean()
ratios_mavg60 = train.rolling(window=60,
                               center=False).mean()
std_60 = train.rolling(window=60,
                        center=False).std()
zscore_60_5 = (ratios_mavg5 - ratios_mavg60)/std_60
plt.figure(figsize=(15,7))
plt.plot(train.index, train.values)
plt.plot(ratios_mavg5.index, ratios_mavg5.values)
plt.plot(ratios_mavg60.index, ratios_mavg60.values)
plt.legend(['Ratio','5d Ratio MA', '60d Ratio MA'])
plt.ylabel('Ratio')
plt.show()

img

60d और 5d MA का मूल्य अनुपात

plt.figure(figsize=(15,7))
zscore_60_5.plot()
plt.axhline(0, color='black')
plt.axhline(1.0, color='red', linestyle='--')
plt.axhline(-1.0, color='green', linestyle='--')
plt.legend(['Rolling Ratio z-Score', 'Mean', '+1', '-1'])
plt.show()

img

60-5 Z स्कोर मूल्य अनुपात

रोलिंग एवरेज के Z स्कोर ने वास्तव में अनुपात के एवरेज रिगोरेशन को उजागर किया है!

चरण 5: मॉडल का चयन

चलो एक बहुत ही सरल मॉडल से शुरू करते हैं. z स्कोर के चार्ट को देखें और हम देख सकते हैं कि जब भी z स्कोर बहुत अधिक या बहुत कम होता है, यह वापस आ जाता है. चलो बहुत अधिक और बहुत कम को परिभाषित करने के लिए + 1 / -1 को हमारे सीमा के रूप में उपयोग करते हैं, और फिर हम निम्नलिखित मॉडल का उपयोग कर सकते हैं व्यापार संकेत उत्पन्न करने के लिएः

  • जब z -1.0 से कम होता है, तो अनुपात खरीदता है))) क्योंकि हम उम्मीद करते हैं कि z 0 पर वापस आ जाएगा, इसलिए अनुपात बढ़ता है।

  • जब z 1.0 से अधिक होता है, तो अनुपात बेच दिया जाता है (−1) क्योंकि हम उम्मीद करते हैं कि z 0 पर वापस आ जाएगा, इसलिए अनुपात कम हो जाता है

चरण 6: प्रशिक्षण, सत्यापन और अनुकूलन

और अंत में, चलो देखते हैं कि हमारे मॉडल का वास्तविक डेटा पर क्या प्रभाव पड़ता है। चलो देखते हैं कि यह संकेत वास्तविक अनुपात में कैसा प्रदर्शन करता है।

# Plot the ratios and buy and sell signals from z score
plt.figure(figsize=(15,7))
train[60:].plot()
buy = train.copy()
sell = train.copy()
buy[zscore_60_5>-1] = 0
sell[zscore_60_5<1] = 0
buy[60:].plot(color=’g’, linestyle=’None’, marker=’^’)
sell[60:].plot(color=’r’, linestyle=’None’, marker=’^’)
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,ratios.min(),ratios.max()))
plt.legend([‘Ratio’, ‘Buy Signal’, ‘Sell Signal’])
plt.show()

img

खरीद और बिक्री मूल्य अनुपात संकेत

यह संकेत उचित लगता है, हम एक उच्च या बढ़ रहा है जब हम बेचने के लिए प्रतीत होता है अनुपात (लाल बिंदु) और यह कम (हरी बिंदु) और घट रहा है जब हम वापस खरीदने के लिए प्रतीत होता है. यह हमारे व्यापार के लिए वास्तविक व्यापार के निशान के लिए क्या मतलब है?

# Plot the prices and buy and sell signals from z score
plt.figure(figsize=(18,9))
S1 = data['ADBE'].iloc[:1762]
S2 = data['MSFT'].iloc[:1762]
S1[60:].plot(color='b')
S2[60:].plot(color='c')
buyR = 0*S1.copy()
sellR = 0*S1.copy()
# When buying the ratio, buy S1 and sell S2
buyR[buy!=0] = S1[buy!=0]
sellR[buy!=0] = S2[buy!=0]
# When selling the ratio, sell S1 and buy S2 
buyR[sell!=0] = S2[sell!=0]
sellR[sell!=0] = S1[sell!=0]
buyR[60:].plot(color='g', linestyle='None', marker='^')
sellR[60:].plot(color='r', linestyle='None', marker='^')
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,min(S1.min(),S2.min()),max(S1.max(),S2.max())))
plt.legend(['ADBE','MSFT', 'Buy Signal', 'Sell Signal'])
plt.show()

img

MSFT और ADBE शेयरों को खरीदने और बेचने के लिए संकेत

कृपया ध्यान दें कि हम कभी-कभी "छोटे पैरों" पर पैसा कैसे कमाते हैं, कभी-कभी "लंबे पैरों" पर पैसा कैसे कमाते हैं, कभी-कभी दोनों।

हम प्रशिक्षण डेटा के संकेतों से संतुष्ट हैं. चलो देखते हैं कि यह संकेत क्या लाभ उत्पन्न कर सकता है. जब अनुपात कम होता है, तो हम एक सरल रीड्यूसर बना सकते हैं, 1 अनुपात खरीदते हैं ((1 ADBE शेयर खरीदने और बेचने का अनुपात x MSFT शेयर) और 1 अनुपात बेचते हैं जब यह उच्च होता है ((1 ADBE शेयर बेचने और खरीदने का अनुपात x MSFT शेयर) और इन अनुपातों के PnL लेनदेन की गणना करते हैं।

# Trade using a simple strategy
def trade(S1, S2, window1, window2):
    
    # If window length is 0, algorithm doesn't make sense, so exit
    if (window1 == 0) or (window2 == 0):
        return 0
    
    # Compute rolling mean and rolling standard deviation
    ratios = S1/S2
    ma1 = ratios.rolling(window=window1,
                               center=False).mean()
    ma2 = ratios.rolling(window=window2,
                               center=False).mean()
    std = ratios.rolling(window=window2,
                        center=False).std()
    zscore = (ma1 - ma2)/std
    
    # Simulate trading
    # Start with no money and no positions
    money = 0
    countS1 = 0
    countS2 = 0
    for i in range(len(ratios)):
        # Sell short if the z-score is > 1
        if zscore[i] > 1:
            money += S1[i] - S2[i] * ratios[i]
            countS1 -= 1
            countS2 += ratios[i]
            print('Selling Ratio %s %s %s %s'%(money, ratios[i], countS1,countS2))
        # Buy long if the z-score is < 1
        elif zscore[i] < -1:
            money -= S1[i] - S2[i] * ratios[i]
            countS1 += 1
            countS2 -= ratios[i]
            print('Buying Ratio %s %s %s %s'%(money,ratios[i], countS1,countS2))
        # Clear positions if the z-score between -.5 and .5
        elif abs(zscore[i]) < 0.75:
            money += S1[i] * countS1 + S2[i] * countS2
            countS1 = 0
            countS2 = 0
            print('Exit pos %s %s %s %s'%(money,ratios[i], countS1,countS2))
            
            
    return money
trade(data['ADBE'].iloc[:1763], data['MSFT'].iloc[:1763], 60, 5)

परिणामः 1783.375

तो यह रणनीति लाभदायक लगती है! अब, हम आगे अनुकूलन कर सकते हैं, जैसे कि चलती औसत समय खिड़की को बदलकर, खरीद / बिक्री की सीमाओं को बदलकर, और सत्यापन डेटा के प्रदर्शन में सुधार की जांच करें।

हम अधिक जटिल मॉडल जैसे कि लॉजिस्टिक रिग्रेशन, एसवीएम आदि का भी प्रयास कर सकते हैं ताकि 1/-1 का अनुमान लगाया जा सके।

अब, चलो इस मॉडल को आगे बढ़ाते हैं, और यह हमें ले जाता है

चरण 7: परीक्षण डेटा का पुनः परीक्षण करें

यहां एक और आविष्कारक क्वांटिफिकेशन प्लेटफॉर्म का उल्लेख है, जो उच्च प्रदर्शन वाले क्यूपीएस/टीपीएस रीसेट इंजन का उपयोग करता है, जो ऐतिहासिक वातावरण को वास्तविक रूप से पुनः पेश करता है, सामान्य मात्रा में रीसेट के जाल को समाप्त करता है, रणनीतियों की कमी को समय पर पहचानता है और इस प्रकार वास्तविक निवेश के लिए बेहतर सहायता प्रदान करता है।

यह लेख सिद्धांतों को समझाने के लिए है, या तो अंतर्निहित तर्क को दिखाने का विकल्प चुनता है, या व्यावहारिक उपयोग में, पाठकों को आविष्कारक क्वांटिफिकेशन प्लेटफॉर्म का उपयोग करने की सलाह देता है, जो समय बचाने के अलावा त्रुटि दर को बढ़ाने के लिए महत्वपूर्ण है।

पुनः परीक्षण बहुत सरल है, हम ऊपर दिए गए फ़ंक्शन का उपयोग कर सकते हैं परीक्षण डेटा के PnL को देखने के लिए

trade(data[‘ADBE’].iloc[1762:], data[‘MSFT’].iloc[1762:], 60, 5)

परिणामः 5262.868

यह मॉडल बहुत अच्छा काम करता है! यह हमारा पहला सरल जोड़ा-जोड़ा लेनदेन मॉडल बन गया।

अत्यधिक फिट होने से बचें

चर्चा को समाप्त करने से पहले, मैं विशेष रूप से अति-अनुकूलन पर चर्चा करना चाहूंगा; अति-अनुकूलन व्यापार रणनीति में सबसे खतरनाक जाल है; अति-अनुकूलन एल्गोरिथ्म पुनर्मूल्यांकन में बहुत अच्छा प्रदर्शन कर सकता है लेकिन नए अदृश्य डेटा पर विफल हो सकता है - जिसका अर्थ है कि यह वास्तव में डेटा में किसी भी प्रवृत्ति को प्रकट नहीं करता है और वास्तव में भविष्यवाणी करने में सक्षम नहीं है; हम एक सरल उदाहरण देते हैं।

हमारे मॉडल में, हम रोलिंग पैरामीटर का उपयोग करके अनुमान लगाते हैं और इसके द्वारा समय खिड़की की लंबाई को अनुकूलित करना चाहते हैं. हम बस सभी संभावनाओं, उचित समय खिड़की की लंबाई को दोहराने का निर्णय ले सकते हैं और समय की लंबाई का चयन कर सकते हैं जो हमारे मॉडल के अनुसार सबसे अच्छा प्रदर्शन करता है. नीचे हम एक सरल लूप लिखते हैं ताकि प्रशिक्षण डेटा के आधार पर पीएनएल को समय खिड़की की लंबाई पर स्कोर किया जा सके और सबसे अच्छा लूप पाया जा सके।

# Find the window length 0-254 
# that gives the highest returns using this strategy
length_scores = [trade(data['ADBE'].iloc[:1762], 
                data['MSFT'].iloc[:1762], l, 5) 
                for l in range(255)]
best_length = np.argmax(length_scores)
print ('Best window length:', best_length)
('Best window length:', 40)

अब जब हम परीक्षण डेटा पर मॉडल के प्रदर्शन की जांच करते हैं, तो हम पाते हैं कि यह समय खिड़की की लंबाई बहुत कम है! यह इसलिए है क्योंकि हमारे मूल विकल्प ने स्पष्ट रूप से नमूना डेटा को बहुत अधिक फिट किया है।

# Find the returns for test data
# using what we think is the best window length
length_scores2 = [trade(data['ADBE'].iloc[1762:], 
                  data['MSFT'].iloc[1762:],l,5) 
                  for l in range(255)]
print (best_length, 'day window:', length_scores2[best_length])
# Find the best window length based on this dataset, 
# and the returns using this window length
best_length2 = np.argmax(length_scores2)
print (best_length2, 'day window:', length_scores2[best_length2])
(40, 'day window:', 1252233.1395)
(15, 'day window:', 1449116.4522)

यह स्पष्ट है कि हमारे लिए उपयुक्त नमूना डेटा हमेशा भविष्य में अच्छे परिणाम नहीं देता है. बस परीक्षण के लिए, चलो दो डेटासेट से गणना की गई लंबाई के अंशों को चित्रित करते हैं।

plt.figure(figsize=(15,7))
plt.plot(length_scores)
plt.plot(length_scores2)
plt.xlabel('Window length')
plt.ylabel('Score')
plt.legend(['Training', 'Test'])
plt.show()

img

हम देख सकते हैं कि 20-50 के बीच कुछ भी समय खिड़की के लिए एक अच्छा विकल्प है।

अत्यधिक अनुकूलन से बचने के लिए, हम आर्थिक तर्क या एल्गोरिदम की प्रकृति का उपयोग करके समय खिड़की की लंबाई का चयन कर सकते हैं। हम कार्लमैन फ़िल्टर का भी उपयोग कर सकते हैं, जिसके लिए हमें लंबाई निर्दिष्ट करने की आवश्यकता नहीं है; बाद में एक अन्य लेख में इस पद्धति का परिचय दिया जाएगा।

अगला कदम

इस लेख में, हम व्यापार रणनीति विकसित करने के लिए प्रक्रिया का प्रदर्शन करने के लिए कुछ सरल परिचयात्मक तरीके प्रस्तुत करते हैं। व्यावहारिक रूप से, अधिक जटिल सांख्यिकीय डेटा का उपयोग करना चाहिए, नीचे दिए गए विकल्पों पर विचार करेंः

  • हर्स्ट सूचकांक

  • अर्नस्टीन-उलेनबेक प्रक्रिया से अनुमानित औसत मूल्य की वापसी का अर्धविराम

  • कार्लमैन फ़िल्टर


संबंधित

अधिक

bk_fundयह पैकेज नहीं मिला

bk_fundजहां बैकटेस्टर.dataSource.yahoo_data_source स्थापित किया जा सकता है