पिछले लेखों में, हमें पता चला कि व्यापार के आदेश कैसे बनाए और संसाधित किए जाते हैं। इस लेख का विषय बाजार विश्लेषण के ग्राफिकल टूल - स्टॉक चार्ट के लिए आवश्यक जानकारी के प्रसंस्करण और भंडारण के मुद्दे होंगे।
शुरू करने से पहले, मैं एक छोटा सा विषयांतर करना चाहता हूं। आंतरिक वोनमो परियोजनाओं के लिए, सामान्य V + शब्द नामकरण योजना का उपयोग किया जाता है, जो कि परियोजना कार्यों के लिए सबसे उपयुक्त है। आज मुझे पता चला कि VTrade एक मौजूदा कंपनी है। भ्रम से बचने के लिए, मैंने प्रयोग को VonmoTrade नाम दिया।
बाजार की स्थिति का आकलन करने के लिए, ऑर्डर और लेनदेन के इतिहास की एक पुस्तक पर्याप्त नहीं है। हमें एक उपकरण की आवश्यकता है जो हमें स्पष्ट रूप से और जल्दी से बाजार मूल्य की प्रवृत्ति की पहचान करने की अनुमति देता है। ट्रेडिंग चार्ट को दो प्रकारों में विभाजित किया जा सकता है:
- रैखिक;
- अंतराल।
रेखा रेखांकन
बिना तैयारी के सबसे सरल और सबसे समझ में आने वाला शेड्यूल। समय पर वित्तीय साधन की कीमत की निर्भरता प्रदर्शित करता है।
इस तरह के ग्राफ का मुख्य लाभ सादगी है। मुख्य दोष यह है कि निम्न जानकारी सामग्री।
यदि चार्ट कच्चे डेटा पर आधारित है, तो अंतिम पास की कीमत ली जाती है। लेकिन आमतौर पर, रेखांकन एकत्रित डेटा के आधार पर बनाया जाता है। इस मामले में, प्रत्येक अंतराल का समापन मूल्य लिया जाता है। चूँकि हम अंतराल में होने वाली हर चीज को त्याग देते हैं और केवल अंतराल का समापन मूल्य लेते हैं, इस वजह से, सूचना सामग्री खो जाती है।
ग्राफिक्स रिज़ॉल्यूशन
यदि हम सभी मूल्य परिवर्तनों के आधार पर एक चार्ट बनाना शुरू करते हैं, अर्थात् प्रत्येक बंद लेनदेन चार्ट पर गिर जाएगा, तो एक व्यक्ति के लिए इसे समझना मुश्किल होगा। और इस तरह के शेड्यूल के प्रसंस्करण और वितरण पर खर्च की जाने वाली शक्ति को अक्षम रूप से खर्च किया जाएगा।
इसलिए, समय अक्ष को अंतरालों में विभाजित करके और इन अंतरालों में कीमतों को एकत्रित करके डेटा को पतला किया जाता है।
संकल्प - समय अक्ष को विभाजित करने के प्राथमिक अंतराल का आकार: दूसरा, मिनट, घंटा, दिन, और इसी तरह।
बार्स
अंतराल चार्ट से संबंधित। सूचना सामग्री को बढ़ाने के लिए, अंतराल के आरंभ और अंत में मूल्य की जानकारी प्रदर्शित करने के लिए प्रत्येक समय अंतराल के साथ-साथ अधिकतम और न्यूनतम मूल्य आवश्यक है। इस सेट के ग्राफिक डिस्प्ले को बार कहा जाता है। एक बार की योजना पर विचार करें:
बार का क्रम एक चार्ट बनाता है:
जापानी मोमबत्तियाँ
सलाखों की तरह, अंतराल चार्ट को देखें। वे तकनीकी विश्लेषण में सबसे लोकप्रिय प्रकार के चार्ट हैं। एक मोमबत्ती में एक काले या सफेद शरीर और छाया होते हैं: ऊपरी और निचले। कभी-कभी एक छाया को बाती कहा जाता है। छाया की ऊपरी और निचली सीमा, इसी अवधि के लिए अधिकतम और न्यूनतम मूल्य प्रदर्शित करती है। शरीर की सीमाएं खुलने और बंद होने की कीमतों को प्रदर्शित करती हैं। आइए एक मोमबत्ती बनाएं:
मोमबत्तियों का क्रम एक ग्राफ बनाता है:
OHLCV संकेतन
पिछले लेख में, हमने पोस्टग्रेज़ल में ग्राफ के लिए डेटा स्टोरेज स्कीम का पता लगाया और डेटा स्रोत के लिए एक तालिका बनाई जो एकत्रित डेटा को संग्रहीत करेगी:
CREATE TABLE df ( t timestamp without time zone NOT NULL, r df_resolution NOT NULL DEFAULT '1m'::df_resolution, o numeric(64,32), h numeric(64,32), l numeric(64,32), c numeric(64,32), v numeric(64,32), CONSTRAINT df_pk PRIMARY KEY (t, r) )
फ़ील्ड्स को स्पष्टीकरण की आवश्यकता नहीं है, सिवाय फ़ील्ड आर श्रृंखला का रिज़ॉल्यूशन है। Postgresql में गणनाएं हैं, वे उपयोग करने के लिए सुविधाजनक हैं जब एक क्षेत्र के लिए मूल्यों का एक सेट अग्रिम में जाना जाता है। गणना के माध्यम से, हम अनुमेय ग्राफ संकल्पों के लिए एक नए प्रकार को परिभाषित करते हैं। इसे एक मिनट से एक महीने तक की श्रृंखला होने दें:
CREATE TYPE df_resolution AS ENUM ('1m', '3m', '5m', '15m', '30m', '45m', '1h', '2h', '4h', '6h', '8h', '12h', '1d', '3d', '1w', '1M');
डिस्क सिस्टम, प्रोसेसर और स्वामित्व की कुल लागत के प्रदर्शन के बीच संतुलन बनाना महत्वपूर्ण है। प्रणाली वर्तमान में 16 प्रस्तावों को परिभाषित करती है। दो समाधान स्पष्ट हैं:
- हम डेटाबेस में सभी प्रस्तावों को गिन और संग्रहीत कर सकते हैं। यह विकल्प उस समय सुविधाजनक है जब नमूना लेना हम अंतराल के एकत्रीकरण पर शक्ति खर्च नहीं करते हैं, सभी डेटा आउटपुट के लिए तुरंत तैयार हैं। एक महीने में, एक उपकरण के लिए 72 हजार से अधिक रिकॉर्ड बनाए जाएंगे। यह सरल और सुविधाजनक लगता है, हालांकि, ऐसी तालिका बहुत बार बदल जाएगी, क्योंकि प्रत्येक मूल्य अपडेट के लिए तालिका में 16 प्रविष्टियों को बनाना या अपडेट करना और सूचकांक का पुनर्निर्माण करना आवश्यक है। Postgresql में, अतिरिक्त रूप से कचरा संग्रहण की समस्या हो सकती है।
- एक अन्य विकल्प एकल मूल संकल्प को संग्रहीत करना है। मूल संकल्प से चयन करते समय, आवश्यक संकल्पों का निर्माण किया जाना चाहिए। उदाहरण के लिए, जब प्रति माह आधार के रूप में मिनट रिज़ॉल्यूशन को संग्रहीत किया जाता है, तो प्रत्येक उपकरण के लिए 43 हजार रिकॉर्ड बनाए जाएंगे। इस प्रकार, पिछले संस्करण की तुलना में, रिकॉर्डिंग और ओवरहेड की मात्रा 40% कम हो जाती है। हालाँकि, प्रोसेसर लोड बढ़ रहा है।
जैसा कि ऊपर उल्लेख किया गया है, एक संतुलन खोजना महत्वपूर्ण है। इसलिए, एक समझौता विकल्प एक मूल संकल्प को संग्रहीत नहीं करना है, लेकिन कई: 1 मिनट, 1 घंटा, 1 दिन। इस योजना के साथ, प्रति माह प्रत्येक उपकरण के लिए 44.6 हजार रिकॉर्ड बनाए जाएंगे। रिकॉर्डिंग वॉल्यूम का अनुकूलन 36% होगा, लेकिन प्रोसेसर पर लोड स्वीकार्य होगा। उदाहरण के लिए, एक मिनट के मूल संकल्प के मामले में 10,080 रिकॉर्ड पढ़ने और एकत्र करने के बजाय साप्ताहिक अंतराल का निर्माण करने के लिए, हमें डिस्क से पढ़ने और केवल 7-दिवसीय प्रस्तावों के डेटा को एकत्र करने की आवश्यकता है।
OHLCV संग्रहण
स्वभाव से, OHLCV एक समय श्रृंखला है। जैसा कि आप जानते हैं, इस तरह के डेटा को संग्रहीत करने और संसाधित करने के लिए एक संबंधपरक डेटाबेस बहुत उपयुक्त नहीं है। इन समस्याओं को हल करने के लिए, प्रोजेक्ट Timescale एक्सटेंशन का उपयोग करता है।
Timescale सम्मिलित और अपडेट संचालन के प्रदर्शन में सुधार करता है, आपको विभाजन को कॉन्फ़िगर करने की अनुमति देता है, और विशेष रूप से समय श्रृंखला के साथ काम करने के लिए अनुकूलित विश्लेषणात्मक फ़ंक्शन प्रदान करता है।
बार बनाने और अपडेट करने के लिए, हमें केवल मानक कार्यों की आवश्यकता है:
date_trunc('minute' | 'hour' | 'day', transaction_ts)
- क्रमशः मिनट, घंटे और दिन के संकल्प के अंतराल की शुरुआत का पता लगाने के लिए।- अधिकतम और न्यूनतम मूल्य निर्धारित करने के लिए
greatest
और greatest
least
।
अपर्चर एपीआई के लिए धन्यवाद, प्रति लेनदेन केवल एक अपडेट अनुरोध निष्पादित किया जाता है।
बुनियादी संकल्पों में बाज़ार परिवर्तन को ठीक करने के लिए मुझे इस तरह का एसक्यूएल मिला:
FOR i IN 1 .. array_upper(storage_resolutions, 1) LOOP resolution = storage_resolutions[i]; IF resolution = '1m' THEN SELECT DATE_TRUNC('minute', ts) INTO bar_start; ELSIF resolution = '1h' THEN SELECT DATE_TRUNC('hour', ts) INTO bar_start; ELSIF resolution = '1d' THEN SELECT DATE_TRUNC('day', ts) INTO bar_start; END IF; EXECUTE format( 'INSERT INTO %I (t,r,o,h,l,c,v) VALUES (%L,%L,%L::numeric,%L::numeric,%L::numeric,%L::numeric,%L::numeric) ON CONFLICT (t,r) DO UPDATE SET h = GREATEST(%Ih, %L::numeric), l = LEAST(%Il, %L::numeric), c = %L::numeric, v = %Iv + %L::numeric;', df_table, bar_start, resolution, price, price, price, price, volume, df_table, price, df_table, price, price, df_table, volume ); END LOOP;
जब नमूने, अंतराल के एकत्रीकरण के लिए, हमें निम्नलिखित कार्यों की आवश्यकता है:
time_bucket
- अंतराल में तोड़ने के लिएfirst
- उद्घाटन मूल्य खोजने के लिए - O
max
- अंतराल के लिए उच्चतम मूल्य - H
min
- प्रति अंतराल सबसे कम मूल्य - L
last
- समापन मूल्य खोजने के लिए - C
sum
- ट्रेडिंग वॉल्यूम खोजने के लिए - V
Timescale का उपयोग करते समय पाई जाने वाली एकमात्र समस्या time_bucket
फ़ंक्शन की time_bucket
हैं। यह आपको एक महीने से भी कम समय के अंतराल पर संचालित करने की अनुमति देता है। एक मासिक रिज़ॉल्यूशन बनाने के लिए, आपको मानक date_trunc
फ़ंक्शन का उपयोग करना होगा।
एपीआई
क्लाइंट पर चार्ट प्रदर्शित करने के लिए, हम ट्रेडिंगव्यू से हल्के-चार्ट का उपयोग करेंगे। पुस्तकालय आपको रेखांकन की उपस्थिति को पूरी तरह से अनुकूलित करने की अनुमति देता है और उपयोग करने के लिए सुविधाजनक है। मुझे निम्नलिखित ग्राफ मिले:
चूंकि ब्राउज़र और प्लेटफ़ॉर्म के बीच इंटरैक्शन का मुख्य हिस्सा वेबसोकेट के माध्यम से है, इसलिए इंटरएक्टिविटी के साथ कोई समस्या नहीं है।
डेटा स्रोत
चार्ट के लिए डेटा स्रोत (डेटा फ़ीड) आवश्यक रिज़ॉल्यूशन में समय श्रृंखला के आवश्यक भाग को वापस करना चाहिए। उसी समय, ट्रैफ़िक को बचाने और क्लाइंट पर प्रसंस्करण समय को कम करने के लिए, सर्वर को बिंदुओं को पैक करना होगा।
डेटा फ़ीड एपीआई को शुरू में डिज़ाइन करने की आवश्यकता है ताकि आप एक अनुरोध में कई चार्टों का अनुरोध कर सकें और उनके अपडेट की सदस्यता ले सकें। यह चैनल में आदेशों और प्रतिक्रियाओं की संख्या को कम करेगा।
यूएसडीपीपी के लिए पिछले 50 मिनट के अनुरोध के एक उदाहरण पर विचार करें, चार्ट अपडेट के लिए एक स्वचालित सदस्यता के साथ:
{ "m":"market", "c":"get_chart", "v":{ "charts":[ { "ticker":"USDGBP", "resolution":"1h", "from":0, "cnt":50, "send_updates":true } ] } }
आप निश्चित रूप से, तारीखों की एक सीमा (से, से) का अनुरोध कर सकते हैं, लेकिन चूंकि प्रत्येक बार के अंतराल को जाना जाता है, घोषित एपीआई कुछ पल और बार की संख्या का संकेत मुझे अधिक सुविधाजनक लगता है।
इस अनुरोध के लिए डेटा फ़ीड एक समान तरीके से प्रतिक्रिया देगा:
{ "m":"market", "c":"chart", "v":{ "bar_fields":[ "t","uts","o","h","l","c","v" ], "items":[ { "ticker":"USDGBP", "resolution":"1h", "bars":[ [ "2019-12-13 13:00:00",1576242000,"0.75236800", "0.76926400","0.75236800","0.76926400","138.10000000" ], .... ] } ] } }
Bar_fields फ़ील्ड में तत्वों की स्थिति के बारे में जानकारी होती है। आगे का अनुकूलन इस क्षेत्र को क्लाइंट कॉन्फ़िगरेशन में रखना है जो इसे बूट समय पर सर्वर से प्राप्त होता है।
इस प्रकार, क्लाइंट ऐतिहासिक डेटा का आवश्यक हिस्सा प्राप्त करता है और ग्राफ की प्रारंभिक स्थिति बनाता है। यदि राज्य बदलता है, तो उसे एक अद्यतन प्राप्त होता है जो केवल अंतिम बार को प्रभावित करता है।
{ "m":"market", "c":"chart_tick", "v":{ "ticker":"USDGBP", "resolution":"1h", "items":{ "v":"140.600", "ut":1576242000, "t":"2019-12-13T13:00:00", "o":"0.752368", "l":"0.752368", "h":"0.770531", "c":"0.770531" } } }
प्रारंभिक परिणाम
लेखों की श्रृंखला के दौरान, हम एक विनिमय के निर्माण के सिद्धांत और व्यवहार का विश्लेषण कर रहे हैं। सिस्टम को एक साथ रखने का समय आ गया है।
अगले लेख में, हम ग्राफिकल यूजर इंटरफेस के विकास को संबोधित करेंगे: प्लेटफ़ॉर्म प्रबंधन के लिए सेवा यूआई और अंतिम उपयोगकर्ताओं के लिए यूआई। वॉनमो ट्रेड का एक डेमो संस्करण भी प्रस्तुत किया जाएगा।