गणितीय विश्लेषण के आधार पर ट्रेडिंग रणनीति विकसित करने का एक बेहतरीन उदाहरण है पेयर ट्रेडिंग। इस लेख में, हम दिखाएंगे कि पेयर ट्रेडिंग रणनीति बनाने और उसे स्वचालित करने के लिए डेटा का लाभ कैसे उठाया जाए।
मान लीजिए कि आपके पास निवेशों की जोड़ी X और Y है, जिनमें कुछ अंतर्निहित सहसंबंध है, जैसे कि दोनों कंपनियां एक ही उत्पाद बनाती हैं, जैसे कि पेप्सी और कोका-कोला। आप चाहते हैं कि दोनों के बीच मूल्य अनुपात या आधार (जिसे स्प्रेड भी कहा जाता है) समय के साथ स्थिर बना रहे। हालांकि, अस्थायी आपूर्ति और मांग में परिवर्तन के कारण समय-समय पर दोनों जोड़ों के बीच अंतर अलग-अलग हो सकता है, जैसे कि एक निवेश लक्ष्य के लिए बड़े खरीद/बिक्री आदेश, किसी एक कंपनी के बारे में महत्वपूर्ण समाचार पर प्रतिक्रिया आदि। इस मामले में, एक निवेश ऊपर की ओर बढ़ता है और दूसरा एक दूसरे के सापेक्ष नीचे की ओर बढ़ता है। यदि आप उम्मीद करते हैं कि यह विचलन समय के साथ सामान्य हो जाएगा, तो आप एक ट्रेडिंग अवसर (या आर्बिट्रेज अवसर) देख सकते हैं। इस तरह के मध्यस्थता के अवसर डिजिटल मुद्रा बाजार या घरेलू कमोडिटी वायदा बाजार में हर जगह मौजूद हैं, जैसे कि बीटीसी और सुरक्षित-हेवन परिसंपत्तियों के बीच संबंध; वायदा में सोयाबीन भोजन, सोयाबीन तेल और सोयाबीन किस्मों के बीच संबंध।
जब अस्थायी मूल्य अंतर होता है, तो ट्रेड बेहतर प्रदर्शन करने वाले निवेश (जो निवेश बढ़ गया है) को बेच देगा और खराब प्रदर्शन करने वाले निवेश (जो निवेश गिर गया है) को खरीद लेगा। आप सुनिश्चित हो सकते हैं कि दोनों निवेशों के बीच अंतर है। स्प्रेड अंततः बेहतर प्रदर्शन करने वाले निवेश के वापस गिरने या खराब प्रदर्शन करने वाले निवेश के वापस ऊपर उठने, या दोनों से परिलक्षित होगा। इन सभी परिदृश्यों में आपका ट्रेड पैसे कमाएगा। यदि निवेशों के बीच का अंतर बदले बिना दोनों एक साथ ऊपर या नीचे जाते हैं, तो आप पैसा न तो कमाएंगे और न ही खोएंगे।
इसलिए, युग्म व्यापार एक बाजार-तटस्थ व्यापार रणनीति है जो व्यापारियों को लगभग किसी भी बाजार स्थिति से लाभ कमाने में सक्षम बनाती है: अपट्रेंड, डाउनट्रेंड या साइडवेज़।
सबसे पहले, सुचारू रूप से काम करने के लिए, हमें अपने शोध वातावरण का निर्माण करने की आवश्यकता है। इस लेख में, हम शोध वातावरण बनाने के लिए इन्वेंटर क्वांटिटेटिव प्लेटफ़ॉर्म (FMZ.COM) का उपयोग करते हैं, मुख्य रूप से इसलिए कि हम सुविधाजनक और तेज़ API का उपयोग कर सकें इस प्लेटफ़ॉर्म का इंटरफ़ेस और एनकैप्सुलेशन बाद में। पूरा Docker सिस्टम।
इन्वेंटर क्वांटिटेटिव प्लेटफॉर्म के आधिकारिक नाम में, इस डॉकर सिस्टम को होस्ट सिस्टम कहा जाता है।
होस्ट और रोबोट को तैनात करने के तरीके के बारे में अधिक जानकारी के लिए, कृपया मेरा पिछला लेख देखें: https://www.fmz.com/bbs-topic/4140
जो पाठक अपना स्वयं का क्लाउड कंप्यूटिंग सर्वर परिनियोजन होस्ट खरीदना चाहते हैं, वे इस लेख का संदर्भ ले सकते हैं: https://www.fmz.com/bbs-topic/2848
क्लाउड कंप्यूटिंग सेवा और होस्ट सिस्टम को सफलतापूर्वक तैनात करने के बाद, हम सबसे शक्तिशाली पायथन टूल स्थापित करेंगे: एनाकोंडा
इस आलेख के लिए आवश्यक सभी प्रासंगिक प्रोग्राम वातावरण (आश्रित लाइब्रेरीज़, संस्करण प्रबंधन, आदि) को प्राप्त करने के लिए, सबसे आसान तरीका एनाकोंडा का उपयोग करना है। यह एक पैकेज्ड पायथन डेटा विज्ञान पारिस्थितिकी तंत्र और निर्भरता प्रबंधक है।
एनाकोंडा की स्थापना विधि के लिए, कृपया एनाकोंडा की आधिकारिक मार्गदर्शिका देखें: https://www.anaconda.com/distribution/
यह आलेख पाइथन वैज्ञानिक कंप्यूटिंग में दो बहुत लोकप्रिय और महत्वपूर्ण लाइब्रेरीज़, numpy और pandas का भी उपयोग करेगा।
उपरोक्त बुनियादी काम के लिए, आप मेरे पिछले लेख को भी देख सकते हैं, जिसमें एनाकोंडा वातावरण और दो लाइब्रेरीज़ numpy और pandas को सेट अप करने का तरीका बताया गया है। विवरण के लिए, कृपया देखें: https://www.fmz.com/digest- विषय/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()
निवेश लक्ष्य X, सामान्य वितरण के माध्यम से इसका दैनिक रिटर्न अनुकरण और आकर्षित करें
अब हम 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()
निवेश लक्ष्य X और Y का सह-एकीकरण
सह-एकीकरण सहसंबंध के बहुत समान है, जिसका अर्थ है कि दो डेटा श्रृंखलाओं के बीच का अनुपात औसत के आसपास अलग-अलग होगा। दो श्रृंखलाएँ Y और X निम्नलिखित का पालन करती हैं:
Y = ⍺ X + e
जहाँ ⍺ एक स्थिर अनुपात है और 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()
दो सह-एकीकृत निवेशों की कीमतों का अनुपात और औसत
इसका परीक्षण करने का एक सुविधाजनक तरीका statsmodels.tsa.stattools का उपयोग करना है। हमें बहुत कम p-मान देखना चाहिए, क्योंकि हमने कृत्रिम रूप से दो डेटा श्रृंखलाएं बनाई हैं जो यथासंभव सह-एकीकृत हैं।
# 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)
दो संबंधित श्रृंखलाएं (सह-एकीकृत नहीं)
सहसंबंध गुणांक: 0.998 सह-एकीकरण परीक्षण p-मान: 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)
सहसंबंध: 0.007546 सह-एकीकरण परीक्षण p-मान: 0.0
सहसंबंध बहुत कम है, लेकिन पी-मान पूर्ण सह-एकीकरण दर्शाता है!
क्योंकि दो सह-एकीकृत समय श्रृंखलाएं (जैसे कि ऊपर एक्स और वाई) एक दूसरे की ओर और एक दूसरे से दूर चलती हैं, ऐसे समय होते हैं जब एक उच्च आधार और एक निम्न आधार होता है। हम एक निवेश खरीदकर और दूसरे को बेचकर जोड़ी ट्रेडिंग करते हैं। इस तरह, यदि दो निवेश लक्ष्य एक साथ गिरते या बढ़ते हैं, तो हम न तो पैसा बनाते हैं और न ही पैसा खोते हैं, यानी हम बाजार तटस्थ हैं।
ऊपर दिए गए Y = ⍺ X + e में X और Y पर वापस जाकर, हम अनुपात (Y/X) को उसके माध्य ⍺ के इर्द-गिर्द घुमाकर पैसे कमाते हैं। ऐसा करने के लिए, हम ध्यान देते हैं कि जब X जब ⍺ का मान बहुत अधिक होता है उच्च या बहुत कम, ⍺ का मान बहुत अधिक या बहुत कम है:
दीर्घ अनुपात: यह तब होता है जब अनुपात ⍺ छोटा होता है और हम इसके बढ़ने की उम्मीद करते हैं। उपरोक्त उदाहरण में, हम Y पर लॉन्ग और X पर शॉर्ट जाकर पोजीशन खोलते हैं।
लघु अनुपात: यह तब होता है जब अनुपात ⍺ बड़ा होता है और हम उम्मीद करते हैं कि यह छोटा हो जाएगा। उपरोक्त उदाहरण में, हम Y को शॉर्ट करके और X को लॉन्ग करके पोजीशन खोलते हैं।
ध्यान दें कि हमारे पास हमेशा एक “हेज्ड स्थिति” होती है: यदि अंतर्निहित लॉन्ग का मूल्य कम हो जाता है, तो शॉर्ट स्थिति से पैसा बनता है, और इसके विपरीत, इसलिए हम समग्र बाजार की गतिविधियों से प्रतिरक्षित होते हैं।
जैसे-जैसे परिसंपत्तियां X और Y एक-दूसरे के सापेक्ष गति करती हैं, हम धन कमाते हैं या धन खोते हैं।
ऐसा करने का सबसे अच्छा तरीका यह है कि आप उन ट्रेडों से शुरुआत करें जिनके बारे में आपको संदेह है कि वे सह-एकीकृत हो सकते हैं और फिर सांख्यिकीय परीक्षण करें। यदि आप सभी व्यापारिक जोड़ों पर सांख्यिकीय परीक्षण करते हैं, तो आपबहु तुलना पूर्वाग्रहका शिकार.
बहु तुलना पूर्वाग्रहउस स्थिति को संदर्भित करता है जहां कई परीक्षण चलाने पर गलत तरीके से महत्वपूर्ण p-मान उत्पन्न होने की संभावना बढ़ जाती है, क्योंकि हमें बड़ी संख्या में परीक्षण चलाने की आवश्यकता होती है। यदि हम यादृच्छिक डेटा पर यह परीक्षण 100 बार चलाते हैं, तो हमें 0.05 से नीचे 5 पी-मान देखने चाहिए। यदि आप सह-एकीकरण के लिए n उपकरणों की तुलना कर रहे हैं, तो आप n(n-1)/2 तुलनाएँ करेंगे और आपको कई गलत p-मान दिखाई देंगे, जो आपके परीक्षण नमूने के आकार के बढ़ने के साथ बढ़ेंगे। और बढ़ेंगे। इससे बचने के लिए, कुछ ऐसे व्यापारिक जोड़ों का चयन करें जिनके बारे में आपको विश्वास हो कि वे सह-एकीकृत हो सकते हैं, और फिर उनका अलग-अलग परीक्षण करें। इससे बहुत हद तक कमी आएगीबहु तुलना पूर्वाग्रह。
तो चलिए कुछ ऐसे उपकरण खोजने की कोशिश करते हैं जो सह-एकीकरण प्रदर्शित करते हैं। आइए S&P 500 में यूएस लार्ज-कैप टेक्नोलॉजी स्टॉक की एक टोकरी लें। ये उपकरण समान बाजार खंडों में काम करते हैं और सह-एकीकरण प्रदर्शित करते हैं। हम व्यापारिक उपकरणों की सूची को स्कैन करते हैं और सभी जोड़ों के बीच सह-एकीकरण का परीक्षण करते हैं।
लौटाए गए सह-एकीकरण परीक्षण स्कोर मैट्रिक्स, पी-मूल्य मैट्रिक्स, तथा 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
नोट: हमने अपने डेटा में बाजार बेंचमार्क (एसपीएक्स) को शामिल किया है - बाजार कई उपकरणों के प्रवाह को संचालित करता है और अक्सर आपको दो उपकरण मिल सकते हैं जो सह-एकीकृत प्रतीत होते हैं; लेकिन वास्तव में वे एक दूसरे के साथ सह-एकीकृत नहीं हैं, बल्कि एक दूसरे के साथ सह-एकीकरण हैं। बाजार. इसे एक भ्रामक चर कहा जाता है। किसी भी संबंध में बाजार की भागीदारी की जांच करना महत्वपूर्ण है।
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)
अब आइए अपनी विधि का उपयोग करके सह-एकीकृत व्यापार जोड़े खोजने का प्रयास करें।
# 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')]
ऐसा लगता है कि ‘ADBE’ और ‘MSFT’ सह-एकीकृत हैं। आइए कीमत पर एक नजर डालें ताकि यह सुनिश्चित हो सके कि यह वास्तव में उचित है।
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()
2008 से 2017 तक एमएसएफटी और एडीबीई के बीच मूल्य अनुपात का चार्ट
यह अनुपात एक स्थिर औसत जैसा दिखता है। सांख्यिकीय दृष्टि से निरपेक्ष अनुपात बहुत उपयोगी नहीं होते। हमारे सिग्नल को z-स्कोर के रूप में देखकर उसे सामान्य बनाना अधिक उपयोगी है। Z स्कोर को इस प्रकार परिभाषित किया गया है:
Z Score (Value) = (Value — Mean) / Standard Deviation
व्यवहार में, हम आमतौर पर डेटा पर कुछ विस्तार लागू करने का प्रयास करते हैं, लेकिन केवल तभी जब डेटा सामान्य रूप से वितरित हो। हालाँकि, अधिकांश वित्तीय डेटा सामान्य रूप से वितरित नहीं होते हैं, इसलिए हमें बहुत सावधान रहना चाहिए कि आंकड़े तैयार करते समय हम सामान्यता या किसी विशेष वितरण को न मान लें। अनुपातों के वास्तविक वितरण में बहुत अधिक असमानताएं हो सकती हैं, तथा चरम सीमा की ओर जाने वाला डेटा हमारे मॉडल को भ्रमित कर सकता है, तथा भारी नुकसान का कारण बन सकता है।
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()
2008 से 2017 तक MSFT और ADBE के बीच Z-मूल्य अनुपात
अब यह देखना आसान है कि अनुपात माध्य के चारों ओर कैसे घूमता है, लेकिन कभी-कभी इसमें माध्य से बड़ा विचलन होता है, जिसका हम फायदा उठा सकते हैं।
अब जबकि हमने जोड़ी ट्रेडिंग रणनीति की मूल बातें पर चर्चा कर ली है और मूल्य इतिहास के आधार पर सह-एकीकरण लक्ष्यों की पहचान कर ली है, तो आइए एक ट्रेडिंग सिग्नल विकसित करने का प्रयास करें। सबसे पहले, आइए डेटा तकनीकों का उपयोग करके ट्रेडिंग सिग्नल विकसित करने के चरणों की समीक्षा करें:
विश्वसनीय डेटा एकत्र करना और डेटा साफ़ करना
ट्रेडिंग सिग्नल/तर्क की पहचान करने के लिए डेटा से फ़ंक्शन बनाएं
विशेषताएं चलती औसत या मूल्य डेटा, सहसंबंध या अधिक जटिल संकेतों के अनुपात हो सकती हैं - नई विशेषताएं बनाने के लिए इन्हें संयोजित करें
ट्रेडिंग सिग्नल उत्पन्न करने के लिए इन सुविधाओं का उपयोग करें, अर्थात कौन से सिग्नल खरीदें, बेचें या शॉर्ट पोजीशन हैं
सौभाग्य से, हमारे पास इनवेंटर क्वांटिटेटिव प्लेटफ़ॉर्म (fmz.com) है जो हमारे लिए उपरोक्त चार पहलुओं को पूरा करता है। यह रणनीति डेवलपर्स के लिए एक बड़ा आशीर्वाद है। हम अपनी ऊर्जा और समय रणनीति तर्क, डिजाइन और कार्यात्मक विस्तार पर खर्च कर सकते हैं।
इन्वेंटर क्वांटिटेटिव प्लेटफ़ॉर्म पर, विभिन्न मुख्यधारा एक्सचेंजों के पैकेज्ड इंटरफ़ेस हैं। हमें बस इन API इंटरफ़ेस को कॉल करना है। बाकी अंतर्निहित कार्यान्वयन तर्क को एक पेशेवर टीम द्वारा पॉलिश किया गया है।
तार्किक पूर्णता और सिद्धांतों की व्याख्या के लिए, हम इन अंतर्निहित तर्कों को विस्तृत तरीके से प्रस्तुत करेंगे, लेकिन वास्तविक संचालन में, पाठक उपरोक्त चार पहलुओं को पूरा करने के लिए सीधे इन्वेंटर क्वांट के एपीआई इंटरफ़ेस को कॉल कर सकते हैं।
आएँ शुरू करें:
यहां हम एक संकेत बनाने की कोशिश कर रहे हैं जो हमें बताता है कि अगले क्षण अनुपात खरीद या बिक्री होगा, जो हमारा भविष्यवक्ता चर Y है:
Y = Ratio is buy (1) or sell (-1)
Y(t)= Sign(Ratio(t+1) — Ratio(t))
ध्यान दें कि हमें अंतर्निहित परिसंपत्ति की वास्तविक कीमत या अनुपात के वास्तविक मूल्य का पूर्वानुमान लगाने की आवश्यकता नहीं है (हालांकि हम ऐसा कर सकते हैं), हमें केवल अनुपात की अगली दिशा का पूर्वानुमान लगाने की आवश्यकता है।
इन्वेंटर क्वांट आपका मित्र है! आप बस उन उपकरणों को निर्दिष्ट करें जिनका आप व्यापार करना चाहते हैं और वह डेटा स्रोत जिसे आप उपयोग करना चाहते हैं, और यह आवश्यक डेटा निकाल लेगा और लाभांश और उपकरण विभाजन के लिए इसे साफ कर देगा। इसलिए यहां हमारा डेटा पहले से ही बहुत साफ है।
हमने पिछले 10 वर्षों के दौरान ट्रेडिंग दिनों के लिए याहू फाइनेंस से निम्नलिखित डेटा का उपयोग किया (लगभग 2,500 डेटा बिंदु): ओपन, क्लोज, हाई, लो और वॉल्यूम
अपने मॉडल की सटीकता का परीक्षण करने के इस अत्यंत महत्वपूर्ण चरण को न भूलें। हम डेटा के निम्नलिखित प्रशिक्षण/सत्यापन/परीक्षण विभाजन का उपयोग कर रहे हैं
Training 7 years ~ 70%
Test ~ 3 years 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()
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()
60-5 Z-स्कोर मूल्य अनुपात
रोलिंग माध्य का Z-स्कोर वास्तव में अनुपात की माध्य-वापसी प्रकृति को सामने लाता है!
आइये एक बहुत ही सरल मॉडल से शुरुआत करें। Z-स्कोर ग्राफ को देखकर हम देख सकते हैं कि जब भी z-स्कोर बहुत अधिक या बहुत कम होता है, तो यह पीछे चला जाता है। आइए हम बहुत अधिक और बहुत कम को परिभाषित करने के लिए +1/-1 को अपनी सीमा के रूप में उपयोग करें, फिर हम ट्रेडिंग सिग्नल उत्पन्न करने के लिए निम्नलिखित मॉडल का उपयोग कर सकते हैं:
जब z -1.0 से नीचे होता है, तो अनुपात खरीदा जाता है (1) क्योंकि हम उम्मीद करते हैं कि z 0 पर वापस आ जाएगा, इसलिए अनुपात बढ़ जाता है
जब z 1.0 से ऊपर होता है, तो अनुपात विक्रय (-1) होता है क्योंकि हम उम्मीद करते हैं कि z 0 पर वापस आ जाएगा, जिससे अनुपात कम हो जाएगा
अंत में, आइए देखें कि हमारे मॉडल का वास्तविक डेटा पर वास्तविक प्रभाव क्या है? आइए देखें कि यह संकेत वास्तविक अनुपात में कैसे व्यवहार करता है
# 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()
खरीदें और बेचें मूल्य अनुपात संकेत
यह संकेत उचित प्रतीत होता है, हम अनुपात को तब बेचते हैं जब यह उच्च या बढ़ रहा होता है (लाल बिंदु) और जब यह निम्न (हरा बिंदु) और घट रहा होता है तो इसे वापस खरीदते हैं। हमारे लेन-देन के वास्तविक विषय-वस्तु के लिए इसका क्या अर्थ है? चलो देखते हैं
# 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()
एमएसएफटी और एडीबीई स्टॉक खरीदने और बेचने के संकेत
ध्यान दें कि कैसे हम कभी-कभी “छोटी टांग” पर पैसा कमाते हैं, कभी-कभी “लंबी टांग” पर, और कभी-कभी दोनों पर।
हम प्रशिक्षण डेटा के संकेत से खुश हैं। आइए देखें कि यह संकेत किस प्रकार का लाभ उत्पन्न कर सकता है। हम एक सरल बैकटेस्टर बना सकते हैं जो 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 भविष्यवाणियों के लिए लॉजिस्टिक रिग्रेशन, एसवीएम आदि जैसे अधिक जटिल मॉडल भी आज़मा सकते हैं।
अब, आइए इस मॉडल को आगे बढ़ाएं, जो हमें इस निष्कर्ष पर पहुंचाता है
यहाँ मैं इन्वेंटर क्वांटिटेटिव प्लेटफ़ॉर्म का ज़िक्र करना चाहूँगा। यह ऐतिहासिक परिवेश को सही मायने में पुन: पेश करने, सामान्य क्वांटिटेटिव बैकटेस्टिंग जाल को खत्म करने और रणनीति की कमियों को तुरंत खोजने के लिए उच्च-प्रदर्शन QPS/TPS बैकटेस्टिंग इंजन का उपयोग करता है, ताकि वास्तविक परिणाम बेहतर तरीके से प्रदान किए जा सकें। -समय निवेश। मदद की पेशकश करें।
सिद्धांत को समझाने के लिए, यह लेख अंतर्निहित तर्क को दिखाने का विकल्प चुनता है। व्यावहारिक अनुप्रयोग में, यह अनुशंसा की जाती है कि पाठक इन्वेंटर क्वांटिटेटिव प्लेटफ़ॉर्म का उपयोग करें। समय बचाने के अलावा, महत्वपूर्ण बात यह है कि दोष सहिष्णुता दर में सुधार करना है।
बैकटेस्टिंग सरल है। हम परीक्षण डेटा के PnL को देखने के लिए उपरोक्त फ़ंक्शन का उपयोग कर सकते हैं।
trade(data[‘ADBE’].iloc[1762:], data[‘MSFT’].iloc[1762:], 60, 5)
परिणाम है: 5262.868
यह मॉडल बहुत अच्छी तरह से बनाया गया है! यह हमारा पहला सरल जोड़ी ट्रेडिंग मॉडल बन गया।
समापन से पहले, मैं विशेष रूप से ओवरफिटिंग के बारे में बात करना चाहता हूं। ट्रेडिंग रणनीतियों में ओवरफिटिंग सबसे खतरनाक गड़बड़ी है। एक ओवरफिटिंग एल्गोरिदम बैकटेस्टिंग में तो बहुत अच्छा प्रदर्शन कर सकता है, लेकिन नए अदृश्य डेटा पर विफल हो सकता है - जिसका अर्थ है कि यह वास्तव में डेटा में कोई रुझान प्रकट नहीं करता है और इसमें कोई वास्तविक पूर्वानुमान शक्ति नहीं है। आइये एक सरल उदाहरण लेते हैं।
हमारे मॉडल में, हम रोलिंग पैरामीटर अनुमानों का उपयोग करते हैं और समय विंडो की लंबाई को अनुकूलित करने की आशा करते हैं। हम सभी संभावनाओं, उचित समय खिड़की की लम्बाइयों पर पुनरावृत्ति करने का निर्णय ले सकते हैं, तथा उस समय अवधि