[TOC]
इस ट्यूटोरियल सीखने से पहले, आप अध्ययन करने की जरूरत हैएफएमजेड क्वांट प्लेटफॉर्म के साथ आरंभ करेंऔरएफएमजेड क्वांट प्लेटफॉर्म के लिए प्राथमिक ट्यूटोरियल रणनीति लेखन, और प्रोग्रामिंग भाषाओं में कुशल बनें।प्राथमिक ट्यूटोरियल में सबसे अधिक उपयोग किए जाने वाले कार्यों को शामिल किया गया है, लेकिन कई ऐसे कार्य और विशेषताएं हैं जिन्हें पेश नहीं किया गया है, और वे इस ट्यूटोरियल में शामिल नहीं होंगे। आपको उन्हें अपने आप को समझने के लिए एफएमजेड प्लेटफॉर्म पर एपीआई दस्तावेज़ ब्राउज़ करने की आवश्यकता है।इस ट्यूटोरियल को सीखने के बाद, आप अधिक मुक्त और अनुकूलित रणनीतियों लिखने में सक्षम हो जाएगा, और FMZ क्वांट मंच सिर्फ एक उपकरण है.
एफएमजेड क्वांट प्लेटफॉर्म सभी समर्थित प्लेटफार्मों को शामिल करता है। एकरूपता बनाए रखने के लिए, एक एकल प्लेटफॉर्म एपीआई के लिए हमारा समर्थन अभी भी पूरा नहीं है। उदाहरण के लिए, गेट रिकॉर्ड्स के-लाइनों की संख्या या प्रारंभ समय में पारित कर सकता है, जबकि यह एफएमजेड प्लेटफॉर्म पर तय है; कुछ प्लेटफॉर्म बैच ऑर्डर का समर्थन करते हैं, जबकि एफएमजेड इसका समर्थन नहीं करता है, और इसी तरह। इसलिए प्लेटफॉर्म डेटा तक सीधे पहुंचने के लिए एक तरीके की आवश्यकता है।सार्वजनिक इंटरफेस के लिए (जैसे बाजार उद्धरण), आप उपयोग कर सकते हैंHttpQuery
, और एन्क्रिप्टेड इंटरफेस (जिसमें खाता जानकारी शामिल है) के लिए आपकोIO
.विशिष्ट इनकमिंग मापदंडों के लिए, कृपया संबंधित मंच एपीआई दस्तावेज़ देखें। पिछले ट्यूटोरियल ने पेश किया है किInfo
फ़ील्ड कच्ची जानकारी लौटाता है, लेकिन यह अभी भी इंटरफ़ेस का समर्थन नहीं करने की समस्या पर कोई फर्क नहीं पड़ता।
यह अंतिम REST एपीआई द्वारा अनुरोधित कच्ची सामग्री (स्ट्रिंग्स) लौटाता है, जिसका उपयोग विस्तारित जानकारी को स्वयं पार्स करने के लिए किया जा सकता है।
function main(){
var account = exchange.GetAccount() //the account doesn't contain all data returned by the request
var raw = JSON.parse(exchange.GetRawJSON())//raw data returned by GetAccount()
Log(raw)
}
सार्वजनिक इंटरफेस का उपयोग करने के लिए, Js उपयोग कर सकते हैंHttpQuery
, और पायथन संबंधित पैकेज का उपयोग कर सकते हैं, जैसे किurllib
याrequests
.
HttpQuery GET विधि के लिए डिफ़ॉल्ट है, और अधिक कार्यों का समर्थन करता है; अधिक विवरण के लिए एपीआई दस्तावेज़ देखें.
var exchangeInfo = JSON.parse(HttpQuery('https://api.binance.com/api/v1/exchangeInfo'))
Log(exchangeInfo)
var ticker = JSON.parse(HttpQuery('https://api.binance.com/api/v1/ticker/24hr'))
var kline = JSON.parse(HttpQuery("https://www.quantinfo.com/API/m/chart/history?symbol=BTC_USD_BITFINEX&resolution=60&from=1525622626&to=1561607596"))
अनुरोधों का उपयोग करके पायथन का उदाहरणः
import requests
resp = requests.get('https://www.quantinfo.com/API/m/chart/history?symbol=BTC_USD_BITFINEX&resolution=60&from=1525622626&to=1561607596')
data = resp.json()
जिन इंटरफेस के लिए एपीआई-की हस्ताक्षर की आवश्यकता होती है, उनके लिए आईओ फ़ंक्शन का उपयोग किया जा सकता है, और उपयोगकर्ताओं को केवल इनकमिंग पैरामीटर की परवाह करने की आवश्यकता होती है, और विशिष्ट हस्ताक्षर प्रक्रिया को अंडरलेयर द्वारा पूरा किया जाएगा।
एफएमजेड प्लेटफॉर्म वर्तमान में बिटमेक्स स्टॉप-लॉस ऑर्डर का समर्थन नहीं करता है, जिसे निम्नलिखित चरणों के अनुसार IO के माध्यम से लागू किया जा सकता हैः
https://www.bitmex.com/api/explorer/
;https://www.bitmex.com/api/v1/order
, विधि के साथPOST
; एफएमजेड के लिए पहले से ही आंतरिक रूप से आधार पता निर्दिष्ट किया है, आपको केवल symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop
.विशिष्ट कोड:
var id = exchange.IO("api", "POST", "/api/v1/order", "symbol=XBTUSD&side=Buy&orderQty=1&stopPx=4000&ordType=Stop")
// You can also pass in the object
var id = exchange.IO("api", "POST", "/api/v1/order", "", JSON.stringify({symbol:"XBTUSD",side:"Buy",orderQty:1,stopPx:4000,ordType:"Stop"}))
अधिक आईओ उदाहरणःhttps://www.fmz.com/bbs-topic/3683
मूल रूप से, सभी क्रिप्टोक्यूरेंसी प्लेटफ़ॉर्म बाजार उद्धरण भेजने के लिए वेबसॉकेट का समर्थन करते हैं, और कुछ प्लेटफ़ॉर्म खाते की जानकारी को अपडेट करने के लिए वेबसॉकेट का समर्थन करते हैं। आराम एपीआई की तुलना में, वेबसॉकेट में आम तौर पर ऐसे फायदे होते हैं, जैसे कम विलंबता, उच्च आवृत्ति और प्लेटफ़ॉर्म आराम एपीआई की आवृत्ति द्वारा सीमित नहीं होना, आदि। नुकसान यह है कि एक रुकावट समस्या है, जिसका प्रसंस्करण सहज नहीं है।
यह लेख मुख्य रूप से परिचय देगा कि जावास्क्रिप्ट भाषा का उपयोग कैसे करें और प्लेटफॉर्म द्वारा कैप्सुलेट किए गए डायल फ़ंक्शन का उपयोग कैसे करें, एफएमजेड क्वांट प्लेटफॉर्म पर कनेक्ट करने के लिए; विशिष्ट निर्देशों और मापदंडों के लिए दस्तावेज़ में हैं, आप डायल के लिए खोज कर सकते हैं; विभिन्न कार्यों को महसूस करने के लिए, डायल फ़ंक्शन को कई बार अपडेट किया गया है। यह लेख इसे कवर करेगा और कई प्लेटफार्मों को जोड़ने के मुद्दे के साथ-साथ wss पर आधारित घटना-संचालित रणनीतियों को पेश करेगा। पायथन डायल फ़ंक्शन, या संबंधित पुस्तकालय का भी उपयोग कर सकता है।
आम तौर पर, सीधे वेबसॉकेट द्वारा कनेक्ट करें; उदाहरण के लिए, बिनेंस ट्रिकर पुश प्राप्त करने के लिएः
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
यदि लौटाए गए डेटा संकुचित प्रारूप में है, तो कनेक्शन करते समय विनिर्देश किया जाना चाहिए;
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
डायल फ़ंक्शन पुनः कनेक्शन का समर्थन करता है, जो अंतर्निहित गोलांग द्वारा किया जाता है। यदि पता लगाया गया कनेक्शन टूट जाता है, तो इसे फिर से जोड़ा जाएगा। अनुरोध डेटा के लिए पहले से ही यूआरएल में, जैसे कि अभी बिनेंस का उदाहरण, यह बहुत सुविधाजनक और अनुशंसित है। उन लोगों के लिए जिन्हें सदस्यता संदेश भेजने की आवश्यकता है, वे स्वयं पुनः कनेक्शन तंत्र को बनाए रख सकते हैं।
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
wss संदेशों की सदस्यता के लिए, कुछ प्लेटफ़ॉर्म अनुरोध यूआरएल में हैं, और कुछ को स्वयं सदस्यता प्राप्त चैनलों को भेजने की आवश्यकता है, जैसे कि सिक्काबेसः
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
सामान्य तौर पर, वेबसॉकेट का उपयोग बाजार के उद्धरणों को पढ़ने के लिए किया जाता है, लेकिन इसका उपयोग ऑर्डर और खाता पुश प्राप्त करने के लिए भी किया जा सकता है। इस तरह के एन्क्रिप्टेड डेटा के पुश में कभी-कभी लंबी देरी होती है और इसका उपयोग सावधानी से किया जाना चाहिए। चूंकि एन्क्रिप्शन विधि अधिक जटिल है, इसलिए यहां संदर्भ के लिए कुछ उदाहरण दिए गए हैं। ध्यान दें कि केवल एक्सेसकी की आवश्यकता होती है, जिसे एक रणनीति पैरामीटर के रूप में सेट किया जा सकता है। यदि सीक्रेटकी की आवश्यकता होती है, तो इसे सुरक्षा सुनिश्चित करने के लिए एक्सचेंज द्वारा निहित रूप से बुलाया जा सकता है।
//Push example of Huobi Futures
var ACCESSKEYID = 'accesskey of your Huobi account'
var apiClient = Dial('wss://api.hbdm.com/notification|compress=gzip&mode=recv')
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var utc_date = new Date(now_utc)
var Timestamp = utc_date.toISOString().substring(0,19)
var quest = 'GET\napi.hbdm.com\n/notification\n'+'AccessKeyId='+ACCESSKEYID+'&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=' + encodeURIComponent(Timestamp)
var signature = exchange.HMAC("sha256", "base64", quest, "{{secretkey} }") // Remove the extra blank spaces between }}
auth = {op: "auth",type: "api",AccessKeyId: ACCESSKEYID, SignatureMethod: "HmacSHA256",SignatureVersion: "2", Timestamp: Timestamp, Signature:encodeURI(signature)}
apiClient.write(JSON.stringify(auth))
apiClient.write('{"op": "sub","cid": "orders","topic": "orders.btc'}')
while (true){
var data = datastream.read()
if('op' in data && data.op == 'ping'){
apiClient.write(JSON.stringify({op:'pong', ts:data.ts}))
}
}
// Push example of Binance; pay attention that listenKey needs to be updated regularly
var APIKEY = 'accesskey of your Binance account'
var req = HttpQuery('https://api.binance.com/api/v3/userDataStream',{method: 'POST',data: ''},null,'X-MBX-APIKEY:'+APIKEY);
var listenKey = JSON.parse(req).listenKey;
HttpQuery('https://api.binance.com/api/v3/userDataStream', {method:'DELETE',data:'listenKey='+listenKey}, null,'X-MBX-APIKEY:'+APIKEY);
listenKey = JSON.parse(HttpQuery('https://api.binance.com/api/v3/userDataStream','',null,'X-MBX-APIKEY:'+APIKEY)).listenKey;
var datastream = Dial("wss://stream.binance.com:9443/ws/"+listenKey+'|reconnect=true',60);
var update_listenKey_time = Date.now()/1000;
while (true){
if (Date.now()/1000 - update_listenKey_time > 1800){
update_listenKey_time = Date.now()/1000;
HttpQuery('https://api.binance.com/api/v3/userDataStream', {method:'PUT',data:'listenKey='+listenKey}, null,'X-MBX-APIKEY:'+APIKEY);
}
var data = datastream.read()
}
// push example of BitMEX
var APIKEY = "your Bitmex API ID"
var expires = parseInt(Date.now() / 1000) + 10
var signature = exchange.HMAC("sha256", "hex", "GET/realtime" + expires, "{{secretkey} }")// secretkey is automatically replaced during execution, so no need to fill in
var client = Dial("wss://www.bitmex.com/realtime", 60)
var auth = JSON.stringify({args: [APIKEY, expires, signature], op: "authKeyExpires"})
var pos = 0
client.write(auth)
client.write('{"op": "subscribe", "args": "position"}')
while (true) {
bitmexData = client.read()
if(bitmexData.table == 'position' && pos != parseInt(bitmexData.data[0].currentQty)){
Log('position change', pos, parseInt(bitmexData.data[0].currentQty), '@')
pos = parseInt(bitmexData.data[0].currentQty)
}
}
आम तौर पर, इसे अनंत लूप में लगातार पढ़ा जा सकता है। कोड इस प्रकार है:
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
while (true) {
var msg = client.read()
var data = JSON.parse(msg) // Parse json strings into quotable objects
// Process data
}
}
wss डेटा पुश गति बहुत तेज़ है. गोलांग की अंडरलेयर कतार में सभी डेटा को कैश करेगी, और जब प्रोग्राम कॉल पढ़ता है, तो डेटा बारी-बारी से वापस कर दिया जाएगा। हालांकि, बॉट पर ऑर्डर देने जैसे ऑपरेशन देरी का कारण बनेंगे, जिसके परिणामस्वरूप डेटा जमा हो सकता है। ट्रेडिंग निष्पादन पुश, खाता पुश और गहराई इंटरपोलेशन पुश जैसी जानकारी के लिए, हमें इतिहास डेटा की आवश्यकता होती है। उद्धरण बाजार डेटा के लिए, ज्यादातर मामलों में, हम केवल नवीनतम डेटा की परवाह करते हैं, इतिहास डेटा नहीं।
यदिread()
कोई पैरामीटर जोड़ता है, यह सबसे पुराना डेटा लौटा देगा, और कोई डेटा नहीं है जब तक वापस ब्लॉक. यदि आप नवीनतम डेटा चाहते हैं, तो आप उपयोग कर सकते हैंclient.read(-2)
नवीनतम डेटा तुरंत वापस करने के लिए, लेकिन जब कोई डेटा नहीं है, यह शून्य लौटाएगा, जो संदर्भ से पहले न्याय करने की आवश्यकता है।
पुराने कैश किए गए डेटा से निपटने के तरीके पर निर्भर करता है और जब कोई डेटा नहीं होता है तो यह अवरुद्ध होता है या नहीं,
इस मामले में यह स्पष्ट है कि
function main() {
var binance = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
var coinbase = Dial("wss://ws-feed.pro.coinbase.com", 60)
coinbase.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
while (true) {
var msgBinance = binance.read(-1) // Parameter -1 represents no data and return null immediately; it will not occur that being blocked before there is data to be returned
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// at this time, Binance has data to return
}
if(msgCoinbase){
// at this time, coinbase has data to return
}
Sleep(1) // Sleep for 1 millisecond
}
}
प्रसंस्करण का यह भाग अधिक कष्टप्रद है, क्योंकि पुश डेटा बाधित हो सकता है, या पुश देरी बेहद लंबी है। भले ही दिल की धड़कन प्राप्त की जा सके, इसका मतलब यह नहीं है कि डेटा अभी भी पुश किया जा रहा है। आप एक घटना अंतराल सेट कर सकते हैं; यदि अंतराल के बाद कोई अपडेट प्राप्त नहीं होता है, तो फिर से कनेक्ट करें; यह देखने के लिए कि डेटा सटीक है या नहीं, यह देखने के लिए समय की अवधि के बाद
पुश डेटा के लिए इस्तेमाल किया गया है, कार्यक्रम स्वाभाविक रूप से घटना-ट्रिगर के रूप में लिखा जाएगा; पुश डेटा की आवृत्ति पर ध्यान दें, क्योंकि उच्च आवृत्ति अनुरोधों को अवरुद्ध होने का कारण होगा; आम तौर पर आप लिख सकते हैंः
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//Here it limits only one trade in 2 seconds
tradeTime = Date.now()
// Trading logic
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//Here it limits GetAccount only once in 5 seconds
accountTime = Date.now()
return exchange.GetAccount()
}
}
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true");
while (true) {
var msg = client.read()
var data = JSON.parse(msg)
var account = GetAccount()
trade(data)
}
}
प्रत्येक प्लेटफ़ॉर्म पर कनेक्शन विधि, डेटा ट्रांसमिशन विधि, सब्सक्राइब की गई सामग्री और वेबसॉकेट का डेटा प्रारूप अक्सर भिन्न होता है, इसलिए प्लेटफ़ॉर्म इसे कैप्सूल नहीं करता है और इसे अपने आप कनेक्ट करने के लिए डायल फ़ंक्शन का उपयोग करने की आवश्यकता होती है। यह लेख मूल रूप से कुछ बुनियादी सावधानियों को कवर करता है। यदि आपके पास कोई और प्रश्न हैं, तो कृपया पूछने के लिए स्वतंत्र महसूस करें।
PS: हालांकि कुछ प्लेटफ़ॉर्म वेबसॉकेट उद्धरण प्रदान नहीं करते हैं, वास्तव में, जब आप डिबगिंग फ़ंक्शन का उपयोग करने के लिए वेबसाइट पर लॉग इन करते हैं, तो आप पाएंगे कि वे सभी वेबसॉकेट पुश का उपयोग कर रहे हैं। शोध करने के बाद, आपको पता चलेगा कि कुछ सदस्यता प्रारूप और रिटर्न प्रारूप एन्क्रिप्टेड प्रतीत होते हैं, जिन्हें base64 के साथ डिकोडिंग और डीकॉम्प्रेसिंग करके देखा जा सकता है।
जावास्क्रिप्ट गो फ़ंक्शन द्वारा समवर्ती को महसूस कर सकता है, और पायथन संबंधित मल्टीथ्रेड लाइब्रेरी का उपयोग कर सकता है।
मात्रात्मक रणनीतियों के कार्यान्वयन के दौरान, समवर्ती निष्पादन समय देरी को कम कर सकता है और दक्षता में सुधार कर सकता है। उदाहरण के लिए हेजिंग रणनीति बॉट को लें। इसे दो सिक्कों की गहराई प्राप्त करने की आवश्यकता है, और क्रम में निष्पादित कोड इस प्रकार दिखाया गया हैः
var depthA = exchanges[0].GetDepth()
var depthB = exchanges[1].GetDepth()
जब एक अनुरोध के विश्राम एपीआई में देरी होती है, उदाहरण के लिए देरी का समय 100 मिलीसेकंड है, तो गहराई दो बार प्राप्त करने का समय वास्तव में अलग है; यदि अधिक पहुँच की आवश्यकता है, तो देरी की समस्या अधिक स्पष्ट होगी, जो रणनीति के निष्पादन को प्रभावित करेगी।
चूंकि जावास्क्रिप्ट में मल्टीथ्रेड नहीं है, इसलिए इस समस्या को हल करने के लिए अंडरलेयर गो फ़ंक्शन को कैप्सूल करता है। गो फ़ंक्शन का उपयोग उन एपीआई के लिए किया जा सकता है जिन्हें नेटवर्क एक्सेस की आवश्यकता होती है, जैसे किGetDepth
, GetAccount
और इसी तरह।IO
यह भी समर्थित है, जैसेःexchange.Go("IO", "api", "POST", "/api/v1/contract_batchorder", "orders_data=" + JSON.stringify(orders))
, लेकिन डिजाइन तंत्र के कारण, इसे लागू करना अधिक थकाऊ है।
var a = exchanges[0].Go("GetDepth")
var b = exchanges[1].Go("GetDepth")
var depthA = a.wait() // Call "wait" method to wait for the return of the asynchronous GetDepth result
var depthB = b.wait()
अधिकांश सरल मामलों में, इस तरह से रणनीतियों को लिखना ठीक है। लेकिन ध्यान दें कि प्रक्रिया हर बार दोहराई जाती है जब रणनीति लूप होती है, और मध्यवर्ती चर a और b वास्तव में केवल अस्थायी रूप से सहायक होते हैं। यदि हमारे पास बहुत सारे समवर्ती कार्य हैं, तो हमें अतिरिक्त रूप से a और depthA, b और depthB के बीच पत्राचार रिकॉर्ड करने की आवश्यकता होती है। जब हमारे समवर्ती कार्य अनिश्चित होते हैं, तो स्थिति अधिक जटिल होती है। इसलिए हम एक फ़ंक्शन को महसूस करने की उम्मीद करते हैंः जब Go फ़ंक्शन को समवर्ती रूप से लिखते हैं, तो एक ही समय में एक चर को बांधें; जब समवर्ती चल परिणाम वापस आता है, तो परिणाम मान स्वचालित रूप से चर को सौंपा जाता है, इस प्रकार मध्यवर्ती चर की आवश्यकता को समाप्त करना और कार्यक्रम को अधिक संक्षिप्त बनाना। विशिष्ट कार्यान्वयन निम्नानुसार हैः
function G(t, ctx, f) {
return {run:function(){
f(t.wait(1000), ctx)
}}
}
हमने एक G फ़ंक्शन को परिभाषित किया है, जहां पैरामीटर
इस समय, समग्र प्रोग्राम फ्रेमवर्क को एक मॉडल के रूप में लिखा जा सकता है, जो
var Info = [{depth:null, account:null}, {depth:null, account:null}] // If we need to obtain the depth and account of the two platforms, more information can also be put in, such as order ID and status, etc.
var tasks = [ ] // Global task list
function produce(){ // Issue all kinds of concurrent tasks
// Here the task producing logic has been omitted, only for demo
tasks.push({exchange:0, ret:'depth', param:['GetDepth']})
tasks.push({exchange:1, ret:'depth', param:['GetDepth']})
tasks.push({exchange:0, ret:'sellID', param:['Buy', Info[0].depth.Asks[0].Price, 10]})
tasks.push({exchange:1, ret:'buyID', param:['Sell', Info[1].depth.Bids[0].Price, 10]})
}
function worker(){
var jobs = []
for(var i=0;i<tasks.length;i++){
var task = tasks[i]
jobs.push(G(exchanges[task.exchange].Go.apply(this, task.param), task, function(v, task) {
Info[task.exchange][task.ret] = v // Here "v" is the return value of the concurrent Go function "wait()", and you can think about it
}))
}
_.each(jobs, function(t){
t.run() // Here all tasks are executed concurrently
})
tasks = []
}
function main() {
while(true){
produce() // Give trading command
worker() // Concurrently execute
Sleep(1000)
}
}
ऐसा लगता है कि उपरोक्त कार्यों में केवल एक सरल फ़ंक्शन को लागू किया गया है। वास्तव में, इसने कोड की जटिलता को बहुत सरल कर दिया है। हमें केवल इस बात की परवाह करने की आवश्यकता है कि प्रोग्राम को क्या कार्य उत्पन्न करने की आवश्यकता है, और
प्रारंभिक ट्यूटोरियल में, ड्राइंग क्लास लाइब्रेरी को ड्राइंग की शुरूआत में अनुशंसित किया गया है, जो ज्यादातर मामलों में जरूरतों को पूरा कर सकता है। यदि आपको आगे अनुकूलन की आवश्यकता है, तो आप सीधे
के आंतरिक मापदंडोंChart({…})
HighStock और HighCharts के ऑब्जेक्ट हैं, लेकिन एक अतिरिक्त पैरामीटर है__isStock
एफएमजेड मुख्य रूप से हाईचार्ट्स और हाईस्टॉक के बुनियादी मॉड्यूल का समर्थन करता है, लेकिन अतिरिक्त मॉड्यूल का समर्थन नहीं करता है।
विशिष्ट हाईचार्ट्स उदाहरणःhttps://www.highcharts.com/demo; हाईस्टॉक उदाहरण:https://www.highcharts.com/stock/demo. आप उन उदाहरणों में कोड का संदर्भ ले सकते हैं, और उन्हें FMZ में आसानी से प्रत्यारोपित कर सकते हैं.
आप निर्दिष्ट सूचकांक के साथ श्रृंखला में डेटा जोड़ने के लिए add ([सीरीज़ इंडेक्स ((जैसे 0), डेटा]) को कॉल कर सकते हैं। चार्ट डेटा को साफ़ करने के लिए call reset (() को कॉल करें; reset एक संख्या पैरामीटर ले सकता है और सहेजने के लिए राशि निर्दिष्ट कर सकता है। एकाधिक चार्ट डिस्प्ले समर्थित है, जिसे केवल कॉन्फ़िगरेशन के दौरान सरणी मापदंडों में पारित करने की आवश्यकता होती है, जैसेः var chart = Chart (([{...}, {...}, {...}]) । उदाहरण के लिए, यदि Chart1 में दो श्रृंखलाएं हैं, Chart2 में एक श्रृंखला है, और Chart3 में एक श्रृंखला है, जब add को कॉल करते हैं, तो श्रृंखला ID 0 और 1 को अपडेट किए गए Chart1 में दो श्रृंखलाओं के डेटा को अलग से प्रतिनिधित्व करने के लिए निर्दिष्ट किया जाता है; श्रृंखला ID 2 को Chart2 में पहली श्रृंखला के डेटा का प्रतिनिधित्व करने के लिए निर्दिष्ट किया जाता है; श्रृंखला ID 3 को Chart3 में पहली श्रृंखला के डेटा का प्रतिनिधित्व करने के लिए निर्दिष्ट किया जाता है।
एक विशिष्ट उदाहरण:
var chart = { // This "chart" in JS is an object; before using the Chart function, we need to declare the object variable of a configured chart "chart"
__isStock: true, // Mark whether it is a general chart; you can change it to false and try to operate it, if you are interested
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // Zoom tool
title : { text : 'spread chart'}, // Theme
rangeSelector: { // Choose the range
buttons: [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
selected: 0,
inputEnabled: false
},
xAxis: { type: 'datetime'}, // Horizontal axis, namely X axis; currently set type: time
yAxis : { // Vertical axis, namely Y axis; the default changes according to the data
title: {text: 'spread'}, // Theme
opposite: false, // whether to enable the vertical axis on the right
},
series : [ // Data series; the attribute saves all kinds of data series (lines, K-lines, labels, etc.)
{name : "line1", id : "line1,buy1Price", data : []}, // The index is 0; the data stroed in the data array is the data of the index series
{name : "line2", id : "line2,lastPrice", dashStyle : 'shortdash', data : []}, // The index is 1; set dashStyle: 'shortdash', namely: set dashed line
]
};
function main(){
var ObjChart = Chart(chart); // Call the Chart function, and initialize the chart
ObjChart.reset(); // Empty
while(true){
var nowTime = new Date().getTime(); // Obtain the timestamp of this polling, namely a millisecond tiemstamp, to ensure the location of writing to the X axis in the chart
var ticker = _C(exchange.GetTicker); // Obtain the market quotes data
var buy1Price = ticker.Buy; // Get buy one price from the return value of the market quotes
var lastPrice = ticker.Last + 1; // Get the final executed price, and we add 1 to split the 2 lines
ObjChart.add([0, [nowTime, buy1Price]]); // Use the timestamp as the value of X, and buy one price as the value of Y; pass in the data series of index 0
ObjChart.add([1, [nowTime, lastPrice]]); // Same as above.
Sleep(2000);
}
}
चार्ट लेआउट का उपयोग करने का उदाहरणःhttps://www.fmz.com/strategy/136056
विशिष्ट ओपन सोर्स पताःhttps://github.com/fmzquant/backtest_python
स्थापना
कमांड लाइन में निम्न कमांड दर्ज करें:
pip install https://github.com/fmzquant/backtest_python/archive/master.zip
सरल उदाहरण
बैकटेस्ट पैरामीटर को टिप्पणी के रूप में रणनीति कोड की शुरुआत में सेट करें, और विवरण एफएमजेड वेबसाइट के
'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"OKEX","currency":"LTC_BTC","balance":3,"stocks":0}]
'''
from fmz import *
task = VCtx(__doc__) # initialize backtest engine from __doc__
print exchange.GetAccount()
print exchange.GetTicker()
print task.Join() # print backtest result
बैकटेस्ट
पूर्ण रणनीतियों के लिए अनंत लूप की आवश्यकता होती है, EOF त्रुटि बैकटेस्ट खत्म होने के बाद उठाई जाएगी; इसलिए, हमें गलती सहिष्णुता को अच्छी तरह से करना चाहिए।
# !/usr/local/bin/python
# -*- coding: UTF-8 -*-
'''backtest
start: 2018-02-19 00:00:00
end: 2018-03-22 12:00:00
period: 15m
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD","balance":10000,"stocks":3}]
'''
from fmz import *
import math
import talib
task = VCtx(__doc__) # initialize backtest engine from __doc__
# ------------------------------ Start of the Strategy --------------------------
print exchange.GetAccount() # Call some interfaces, and print their return values
print exchange.GetTicker()
def adjustFloat(v): # the custom functions in the strategy
v = math.floor(v * 1000)
return v / 1000
def onTick():
Log("onTick")
# Specific strategy code
def main():
InitAccount = GetAccount()
while True:
onTick()
Sleep(1000)
# ------------------------------ End of the Strategy --------------------------
try:
main() # The end of the backtest will raise EOFError() to stop stop the backtest loop. Therefore, we should handle with the error, and call task.Join() to print the backtest result, after the error is detected
except:
print task.Join()
exchange.SetData(arr) बैकटेस्ट डेटा स्रोत स्विच करता है और कस्टम K-लाइन डेटा का उपयोग करता है। पैरामीटर
arr के सरणी में, एक एकल तत्व का डेटा प्रारूपः
[
1530460800, // time Timestamp
2841.5795, // open Open Price
2845.6801, // high Highest Price
2756.815, // low Lowest Price
2775.557, // close Close Price
137035034 // volume Executed Volume
]
function init() { // The init function in the template will be executed first when the template is loaded; ensure the exchange.SetData(arr) function is executed first, initialized, and set the data to the backtest system
var arr = [ // The K-line data to be used during backtest
[1530460800,2841.5795,2845.6801,2756.815,2775.557,137035034], // The data of the earliest K-line bar
... , // If the K-line data is too long, use "..." to represent the omitted data here
[1542556800,2681.8988,2703.5116,2674.1781,2703.5116,231662827] // The data of the latest K-line bar
]
exchange.SetData(arr) // Import the custom data mentioned above
Log("Import data successfully")
}
नोटः प्रारंभ के दौरान पहले कस्टम डेटा आयात करना सुनिश्चित करें (यानी, डेटा सेट करने के लिए एक्सचेंज.सेटडाटा फ़ंक्शन को कॉल करें). कस्टम के-लाइन डेटा अवधि बैकटेस्ट पृष्ठ पर सेट अंडरलेयर के-लाइन अवधि के अनुरूप होनी चाहिए, अर्थातः कस्टम के-लाइन डेटा; एक के-लाइन का समय 1 मिनट है, इसलिए बैकटेस्ट में सेट अंडरलेयर के-लाइन की अवधि भी 1 मिनट पर सेट होनी चाहिए।
यदि असमर्थित प्लेटफ़ॉर्म का एपीआई आधार पते को छोड़कर, समर्थित प्लेटफ़ॉर्म के समान है, तो असमर्थित प्लेटफ़ॉर्म को आधार पते को स्विच करके समर्थित किया जा सकता है। विशिष्ट होने के लिए, प्लेटफ़ॉर्म जोड़ते समय एक समर्थित प्लेटफ़ॉर्म का चयन करें, लेकिन असमर्थित प्लेटफ़ॉर्म की एपीआई-की को भरें, और रणनीति में आधार पते को स्विच करने के लिए IO का उपयोग करें, जैसेः
exchange.IO("base", "http://api.huobi.pro")
//http://api.huobi.pro is the base address of the unsupported platform API, and notice not to add api/v3 and so on, for the address will be automatically completed
एफएमजेड द्वारा सभी प्लेटफार्मों का समर्थन नहीं किया जाता है, लेकिन हमारे प्लेटफॉर्म ने सामान्य प्रोटोकॉल की पहुंच विधि प्रदान की है। विशिष्ट सिद्धांत हैंः
सरल शब्दों में कहें तो सामान्य प्रोटोकॉल एक मध्यस्थ की तरह है, जो डॉकर के अनुरोध को प्रॉक्सी करता है और संबंधित मानक के अनुसार डेटा लौटाता है। सामान्य प्रोटोकॉल का कोड स्वयं को पूरा करने की आवश्यकता होती है। सामान्य प्रोटोकॉल लिखने का वास्तव में मतलब है कि आप केवल मंच तक पहुंच सकते हैं और रणनीति को पूरा कर सकते हैं। एफएमजेड आधिकारिक कभी-कभी प्लेटफार्मों के सामान्य प्रोटोकॉल का exe संस्करण जारी करता है। सामान्य प्रोटोकॉल पायथन में भी किया जा सकता है, जिसे फिर एक साधारण बॉट के रूप में डॉकर पर चलाया जा सकता है।
सामान्य प्रोटोकॉल का विशिष्ट परिचय:https://www.fmz.com/bbs-topic/9120पायथन में सामान्य प्रोटोकॉल लिखने का उदाहरणःhttps://www.fmz.com/strategy/101399
जैसे किसी प्लेटफ़ॉर्म के विभिन्न संचालन को एपीआई के माध्यम से लागू किया जा सकता है, वैसे ही एफएमजेड वेबसाइट भी एपीआई पर आधारित है। आप एपीआई दस्तावेज़ में अपने स्वयं के एपीआई-की के लिए आवेदन कर सकते हैं, जैसे कि
एफएमजेड क्वांट प्लेटफ़ॉर्म की शक्तिशाली विस्तारशीलता के कारण, आप एपीआई एक्सटेंशन के आधार पर अपना स्वयं का मात्रात्मक प्लेटफ़ॉर्म बना सकते हैं, जिससे आपके उपयोगकर्ता आपके प्लेटफ़ॉर्म पर बॉट चला सकते हैं, आदि। विशिष्ट संदर्भःhttps://www.fmz.com/bbs-topic/1697 .
क्रिप्टोक्यूरेंसी ट्रेडिंग बाजार ने अपनी विशिष्टता के कारण मात्रात्मक व्यापारियों से अधिक से अधिक ध्यान आकर्षित किया है। वास्तव में, प्रोग्राम ट्रेडिंग क्रिप्टोक्यूरेंसी की मुख्यधारा बन गई है, और हेजिंग और मार्केट मेकिंग जैसी रणनीतियाँ हमेशा बाजार में सक्रिय होती हैं। कमजोर प्रोग्रामिंग नींव वाले शुरुआती इस नए क्षेत्र में प्रवेश करना चाहते हैं, कई प्लेटफार्मों और बदलते एपीआई का सामना करते हुए, कठिनाइयों से भरे हुए हैं। एफएमजेड क्वांट प्लेटफॉर्म, (पूर्व बॉटवी,www.fmz.com) वर्तमान में सबसे बड़ा क्रिप्टोक्यूरेंसी मात्रात्मक समुदाय और मंच है, जिसने 4 से अधिक वर्षों के लिए मात्रात्मक व्यापार की सड़क पर हजारों शुरुआती लोगों की मदद की है। नेटईज़ पर पाठ्यक्रम लेने के लिए, आपको केवल 20 युआन लगते हैं, और पाठ्यक्रम पूरी तरह से शुरुआती के लिए है।
प्रोत्साहननेटईज़ क्लाउड क्लासरूम पर क्रिप्टोकरेंसी मात्रात्मक ट्रेडिंग कोर्स. नेटईज़ क्लाउड क्लासरूम में लॉग इन करें और अपना कोर्स लिंक साझा करें (लिंक में एक अद्वितीय कोर्स आईडी है). अन्य, जो इस लिंक के माध्यम से पाठ्यक्रम को पंजीकृत करते हैं और खरीदते हैं, आपको कुल का 50% कमीशन के रूप में लाएंगे, अर्थात् 10 युआन। नकदी निकालने के लिए
प्रमोशन लिंक पर क्लिक करने, पंजीकरण करने और आधे वर्ष के भीतर रिचार्ज करने वाले उपभोक्ताओं को इस नीति का लाभ मिलेगा कि हमारी कंपनी वैध क्रम में प्रभावी राशि के अनुसार छूट देगी। कमीशन को प्रमोटर के खाते में अंक के रूप में वापस कर दिया जाएगा। उपयोगकर्ता एफएमजेड प्लेटफॉर्म के खाते के शेष राशि में 10: 1 के अनुपात में अंक का आदान-प्रदान कर सकते हैं, और उपयोगकर्ता भविष्य में एफएमजेड क्वांट के संबंधित उत्पादों का आदान-प्रदान करने के लिए भी अंक का उपयोग कर सकते हैं। गतिविधि के लिए विशिष्ट लिंकःhttps://www.fmz.com/bbs-topic/3828
पूर्ण एफएमजेड वेबसाइट को पूर्ण नियंत्रण और कार्यात्मक अनुकूलन के लिए किसी उद्यम या टीम के विशेष सर्वर पर तैनात किया जा सकता है। एफएमजेड वेबसाइट का उपयोग और परीक्षण लगभग 100,000 उपयोगकर्ताओं द्वारा किया गया है, और उच्च उपलब्धता और सुरक्षा प्राप्त की है, जो मात्रात्मक टीमों और उद्यमों के लिए समय बचा सकती है। उद्यम संस्करण मध्यम आकार के मात्रात्मक व्यापार टीमों, कमोडिटी वायदा सेवा प्रदाताओं, आदि के लिए है। विशिष्ट उद्धरण के लिए कृपया व्यवस्थापक से संपर्क करें।
पेशेवर प्रणाली, जो प्लेटफार्मों के लिए बाजार तरलता और धन प्रबंधन प्रदान करती है, बाजार में सबसे बेहतर बाजार बनाने की प्रणाली हो सकती है। यह कई प्लेटफार्मों और टीमों द्वारा व्यापक रूप से उपयोग की जाती है।
एफएमजेड प्रौद्योगिकी व्यापार प्रणाली मेमोरी मिलान तकनीक को अपनाती है, और ऑर्डर प्रोसेसिंग की गति 2 मिलियन ट्रेड प्रति सेकंड तक होती है, जो यह सुनिश्चित कर सकती है कि ऑर्डर प्रोसेसिंग में कोई देरी या देरी नहीं होगी। यह 20 मिलियन से अधिक एक साथ ऑनलाइन उपयोगकर्ताओं के साथ प्लेटफार्मों के सुचारू और स्थिर संचालन को बनाए रख सकती है। बहु-परत और बहु-क्लस्टर सिस्टम फ्रेमवर्क सिस्टम की सुरक्षा, स्थिरता और विस्तार को सुनिश्चित करता है। फ़ंक्शन की तैनाती और संस्करण अपडेट डाउनटाइम के बिना किया जा सकता है, जो टर्मिनल उपयोगकर्ताओं के ऑपरेटिंग अनुभव की अधिकतम गारंटी देता है। वर्तमान में, सिस्टम को wex.app सिमुलेटेड प्लेटफॉर्म में अनुभव किया जा सकता है।